MOAB  4.9.3pre
SparseCompressedBase.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2015 Gael Guennebaud <[email protected]>
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_SPARSE_COMPRESSED_BASE_H
00011 #define EIGEN_SPARSE_COMPRESSED_BASE_H
00012 
00013 namespace Eigen { 
00014 
00015 template<typename Derived> class SparseCompressedBase;
00016   
00017 namespace internal {
00018 
00019 template<typename Derived>
00020 struct traits<SparseCompressedBase<Derived> > : traits<Derived>
00021 {};
00022 
00023 } // end namespace internal
00024 
00035 template<typename Derived>
00036 class SparseCompressedBase
00037   : public SparseMatrixBase<Derived>
00038 {
00039   public:
00040     typedef SparseMatrixBase<Derived> Base;
00041     EIGEN_SPARSE_PUBLIC_INTERFACE(SparseCompressedBase)
00042     using Base::operator=;
00043     using Base::IsRowMajor;
00044     
00045     class InnerIterator;
00046     class ReverseInnerIterator;
00047     
00048   protected:
00049     typedef typename Base::IndexVector IndexVector;
00050     Eigen::Map<IndexVector> innerNonZeros() { return Eigen::Map<IndexVector>(innerNonZeroPtr(), isCompressed()?0:derived().outerSize()); }
00051     const  Eigen::Map<const IndexVector> innerNonZeros() const { return Eigen::Map<const IndexVector>(innerNonZeroPtr(), isCompressed()?0:derived().outerSize()); }
00052         
00053   public:
00054     
00056     inline Index nonZeros() const
00057     {
00058       if(Derived::IsVectorAtCompileTime && outerIndexPtr()==0)
00059         return derived().nonZeros();
00060       else if(isCompressed())
00061         return outerIndexPtr()[derived().outerSize()]-outerIndexPtr()[0];
00062       else if(derived().outerSize()==0)
00063         return 0;
00064       else
00065         return innerNonZeros().sum();
00066     }
00067     
00071     inline const Scalar* valuePtr() const { return derived().valuePtr(); }
00075     inline Scalar* valuePtr() { return derived().valuePtr(); }
00076 
00080     inline const StorageIndex* innerIndexPtr() const { return derived().innerIndexPtr(); }
00084     inline StorageIndex* innerIndexPtr() { return derived().innerIndexPtr(); }
00085 
00090     inline const StorageIndex* outerIndexPtr() const { return derived().outerIndexPtr(); }
00095     inline StorageIndex* outerIndexPtr() { return derived().outerIndexPtr(); }
00096 
00100     inline const StorageIndex* innerNonZeroPtr() const { return derived().innerNonZeroPtr(); }
00104     inline StorageIndex* innerNonZeroPtr() { return derived().innerNonZeroPtr(); }
00105     
00107     inline bool isCompressed() const { return innerNonZeroPtr()==0; }
00108 
00109   protected:
00111     SparseCompressedBase() {}
00112   private:
00113     template<typename OtherDerived> explicit SparseCompressedBase(const SparseCompressedBase<OtherDerived>&);
00114 };
00115 
00116 template<typename Derived>
00117 class SparseCompressedBase<Derived>::InnerIterator
00118 {
00119   public:
00120     InnerIterator()
00121       : m_values(0), m_indices(0), m_outer(0), m_id(0), m_end(0)
00122     {}
00123 
00124     InnerIterator(const InnerIterator& other)
00125       : m_values(other.m_values), m_indices(other.m_indices), m_outer(other.m_outer), m_id(other.m_id), m_end(other.m_end)
00126     {}
00127 
00128     InnerIterator& operator=(const InnerIterator& other)
00129     {
00130       m_values = other.m_values;
00131       m_indices = other.m_indices;
00132       const_cast<OuterType&>(m_outer).setValue(other.m_outer.value());
00133       m_id = other.m_id;
00134       m_end = other.m_end;
00135       return *this;
00136     }
00137 
00138     InnerIterator(const SparseCompressedBase& mat, Index outer)
00139       : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer)
00140     {
00141       if(Derived::IsVectorAtCompileTime && mat.outerIndexPtr()==0)
00142       {
00143         m_id = 0;
00144         m_end = mat.nonZeros();
00145       }
00146       else
00147       {
00148         m_id = mat.outerIndexPtr()[outer];
00149         if(mat.isCompressed())
00150           m_end = mat.outerIndexPtr()[outer+1];
00151         else
00152           m_end = m_id + mat.innerNonZeroPtr()[outer];
00153       }
00154     }
00155 
00156     explicit InnerIterator(const SparseCompressedBase& mat)
00157       : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(0), m_id(0), m_end(mat.nonZeros())
00158     {
00159       EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00160     }
00161 
00162     explicit InnerIterator(const internal::CompressedStorage<Scalar,StorageIndex>& data)
00163       : m_values(data.valuePtr()), m_indices(data.indexPtr()), m_outer(0), m_id(0), m_end(data.size())
00164     {
00165       EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00166     }
00167 
00168     inline InnerIterator& operator++() { m_id++; return *this; }
00169 
00170     inline const Scalar& value() const { return m_values[m_id]; }
00171     inline Scalar& valueRef() { return const_cast<Scalar&>(m_values[m_id]); }
00172 
00173     inline StorageIndex index() const { return m_indices[m_id]; }
00174     inline Index outer() const { return m_outer.value(); }
00175     inline Index row() const { return IsRowMajor ? m_outer.value() : index(); }
00176     inline Index col() const { return IsRowMajor ? index() : m_outer.value(); }
00177 
00178     inline operator bool() const { return (m_id < m_end); }
00179 
00180   protected:
00181     const Scalar* m_values;
00182     const StorageIndex* m_indices;
00183     typedef internal::variable_if_dynamic<Index,Derived::IsVectorAtCompileTime?0:Dynamic> OuterType;
00184     const OuterType m_outer;
00185     Index m_id;
00186     Index m_end;
00187   private:
00188     // If you get here, then you're not using the right InnerIterator type, e.g.:
00189     //   SparseMatrix<double,RowMajor> A;
00190     //   SparseMatrix<double>::InnerIterator it(A,0);
00191     template<typename T> InnerIterator(const SparseMatrixBase<T>&, Index outer);
00192 };
00193 
00194 template<typename Derived>
00195 class SparseCompressedBase<Derived>::ReverseInnerIterator
00196 {
00197   public:
00198     ReverseInnerIterator(const SparseCompressedBase& mat, Index outer)
00199       : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer)
00200     {
00201       if(Derived::IsVectorAtCompileTime && mat.outerIndexPtr()==0)
00202       {
00203         m_start = 0;
00204         m_id = mat.nonZeros();
00205       }
00206       else
00207       {
00208         m_start.value() = mat.outerIndexPtr()[outer];
00209         if(mat.isCompressed())
00210           m_id = mat.outerIndexPtr()[outer+1];
00211         else
00212           m_id = m_start.value() + mat.innerNonZeroPtr()[outer];
00213       }
00214     }
00215 
00216     explicit ReverseInnerIterator(const SparseCompressedBase& mat)
00217       : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(0), m_start(0), m_id(mat.nonZeros())
00218     {
00219       EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00220     }
00221 
00222     explicit ReverseInnerIterator(const internal::CompressedStorage<Scalar,StorageIndex>& data)
00223       : m_values(data.valuePtr()), m_indices(data.indexPtr()), m_outer(0), m_start(0), m_id(data.size())
00224     {
00225       EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00226     }
00227 
00228     inline ReverseInnerIterator& operator--() { --m_id; return *this; }
00229 
00230     inline const Scalar& value() const { return m_values[m_id-1]; }
00231     inline Scalar& valueRef() { return const_cast<Scalar&>(m_values[m_id-1]); }
00232 
00233     inline StorageIndex index() const { return m_indices[m_id-1]; }
00234     inline Index outer() const { return m_outer.value(); }
00235     inline Index row() const { return IsRowMajor ? m_outer.value() : index(); }
00236     inline Index col() const { return IsRowMajor ? index() : m_outer.value(); }
00237 
00238     inline operator bool() const { return (m_id > m_start.value()); }
00239 
00240   protected:
00241     const Scalar* m_values;
00242     const StorageIndex* m_indices;
00243     const internal::variable_if_dynamic<Index,Derived::IsVectorAtCompileTime?0:Dynamic> m_outer;
00244     Index m_id;
00245     const internal::variable_if_dynamic<Index,Derived::IsVectorAtCompileTime?0:Dynamic> m_start;
00246 };
00247 
00248 namespace internal {
00249 
00250 template<typename Derived>
00251 struct evaluator<SparseCompressedBase<Derived> >
00252   : evaluator_base<Derived>
00253 {
00254   typedef typename Derived::Scalar Scalar;
00255   typedef typename Derived::InnerIterator InnerIterator;
00256   typedef typename Derived::ReverseInnerIterator ReverseInnerIterator;
00257   
00258   enum {
00259     CoeffReadCost = NumTraits<Scalar>::ReadCost,
00260     Flags = Derived::Flags
00261   };
00262   
00263   evaluator() : m_matrix(0)
00264   {
00265     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00266   }
00267   explicit evaluator(const Derived &mat) : m_matrix(&mat)
00268   {
00269     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00270   }
00271   
00272   inline Index nonZerosEstimate() const {
00273     return m_matrix->nonZeros();
00274   }
00275   
00276   operator Derived&() { return m_matrix->const_cast_derived(); }
00277   operator const Derived&() const { return *m_matrix; }
00278   
00279   typedef typename DenseCoeffsBase<Derived,ReadOnlyAccessors>::CoeffReturnType CoeffReturnType;
00280   Scalar coeff(Index row, Index col) const
00281   { return m_matrix->coeff(row,col); }
00282   
00283   Scalar& coeffRef(Index row, Index col)
00284   {
00285     eigen_internal_assert(row>=0 && row<m_matrix->rows() && col>=0 && col<m_matrix->cols());
00286       
00287     const Index outer = Derived::IsRowMajor ? row : col;
00288     const Index inner = Derived::IsRowMajor ? col : row;
00289 
00290     Index start = m_matrix->outerIndexPtr()[outer];
00291     Index end = m_matrix->isCompressed() ? m_matrix->outerIndexPtr()[outer+1] : m_matrix->outerIndexPtr()[outer] + m_matrix->innerNonZeroPtr()[outer];
00292     eigen_assert(end>start && "you are using a non finalized sparse matrix or written coefficient does not exist");
00293     const Index p =   std::lower_bound(m_matrix->innerIndexPtr()+start, m_matrix->innerIndexPtr()+end,inner)
00294                     - m_matrix->innerIndexPtr();
00295     eigen_assert((p<end) && (m_matrix->innerIndexPtr()[p]==inner) && "written coefficient does not exist");
00296     return m_matrix->const_cast_derived().valuePtr()[p];
00297   }
00298 
00299   const Derived *m_matrix;
00300 };
00301 
00302 }
00303 
00304 } // end namespace Eigen
00305 
00306 #endif // EIGEN_SPARSE_COMPRESSED_BASE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines