// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_MAP_H #define EIGEN_SPARSE_MAP_H namespace Eigen { namespace internal { template struct traits, Options, StrideType> > : public traits > { typedef SparseMatrix PlainObjectType; typedef traits TraitsBase; enum { Flags = TraitsBase::Flags & (~NestByRefBit) }; }; template struct traits, Options, StrideType> > : public traits > { typedef SparseMatrix PlainObjectType; typedef traits TraitsBase; enum { Flags = TraitsBase::Flags & (~ (NestByRefBit | LvalueBit)) }; }; } // end namespace internal template::has_write_access ? WriteAccessors : ReadOnlyAccessors > class SparseMapBase; /** \ingroup SparseCore_Module * class SparseMapBase * \brief Common base class for Map and Ref instance of sparse matrix and vector. */ template class SparseMapBase : public SparseCompressedBase { public: typedef SparseCompressedBase Base; typedef typename Base::Scalar Scalar; typedef typename Base::StorageIndex StorageIndex; enum { IsRowMajor = Base::IsRowMajor }; using Base::operator=; protected: typedef typename internal::conditional< bool(internal::is_lvalue::value), Scalar *, const Scalar *>::type ScalarPointer; typedef typename internal::conditional< bool(internal::is_lvalue::value), StorageIndex *, const StorageIndex *>::type IndexPointer; Index m_outerSize; Index m_innerSize; Array m_zero_nnz; IndexPointer m_outerIndex; IndexPointer m_innerIndices; ScalarPointer m_values; IndexPointer m_innerNonZeros; public: /** \copydoc SparseMatrixBase::rows() */ inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; } /** \copydoc SparseMatrixBase::cols() */ inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; } /** \copydoc SparseMatrixBase::innerSize() */ inline Index innerSize() const { return m_innerSize; } /** \copydoc SparseMatrixBase::outerSize() */ inline Index outerSize() const { return m_outerSize; } /** \copydoc SparseCompressedBase::nonZeros */ inline Index nonZeros() const { return m_zero_nnz[1]; } /** \copydoc SparseCompressedBase::isCompressed */ bool isCompressed() const { return m_innerNonZeros==0; } //---------------------------------------- // direct access interface /** \copydoc SparseMatrix::valuePtr */ inline const Scalar* valuePtr() const { return m_values; } /** \copydoc SparseMatrix::innerIndexPtr */ inline const StorageIndex* innerIndexPtr() const { return m_innerIndices; } /** \copydoc SparseMatrix::outerIndexPtr */ inline const StorageIndex* outerIndexPtr() const { return m_outerIndex; } /** \copydoc SparseMatrix::innerNonZeroPtr */ inline const StorageIndex* innerNonZeroPtr() const { return m_innerNonZeros; } //---------------------------------------- /** \copydoc SparseMatrix::coeff */ inline Scalar coeff(Index row, Index col) const { const Index outer = IsRowMajor ? row : col; const Index inner = IsRowMajor ? col : row; Index start = m_outerIndex[outer]; Index end = isCompressed() ? m_outerIndex[outer+1] : start + m_innerNonZeros[outer]; if (start==end) return Scalar(0); else if (end>0 && inner==m_innerIndices[end-1]) return m_values[end-1]; // ^^ optimization: let's first check if it is the last coefficient // (very common in high level algorithms) const StorageIndex* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner); const Index id = r-&m_innerIndices[0]; return ((*r==inner) && (id(nnz)), m_outerIndex(outerIndexPtr), m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(innerNonZerosPtr) {} // for vectors inline SparseMapBase(Index size, Index nnz, IndexPointer innerIndexPtr, ScalarPointer valuePtr) : m_outerSize(1), m_innerSize(size), m_zero_nnz(0,internal::convert_index(nnz)), m_outerIndex(m_zero_nnz.data()), m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(0) {} /** Empty destructor */ inline ~SparseMapBase() {} protected: inline SparseMapBase() {} }; /** \ingroup SparseCore_Module * class SparseMapBase * \brief Common base class for writable Map and Ref instance of sparse matrix and vector. */ template class SparseMapBase : public SparseMapBase { typedef MapBase ReadOnlyMapBase; public: typedef SparseMapBase Base; typedef typename Base::Scalar Scalar; typedef typename Base::StorageIndex StorageIndex; enum { IsRowMajor = Base::IsRowMajor }; using Base::operator=; public: //---------------------------------------- // direct access interface using Base::valuePtr; using Base::innerIndexPtr; using Base::outerIndexPtr; using Base::innerNonZeroPtr; /** \copydoc SparseMatrix::valuePtr */ inline Scalar* valuePtr() { return Base::m_values; } /** \copydoc SparseMatrix::innerIndexPtr */ inline StorageIndex* innerIndexPtr() { return Base::m_innerIndices; } /** \copydoc SparseMatrix::outerIndexPtr */ inline StorageIndex* outerIndexPtr() { return Base::m_outerIndex; } /** \copydoc SparseMatrix::innerNonZeroPtr */ inline StorageIndex* innerNonZeroPtr() { return Base::m_innerNonZeros; } //---------------------------------------- /** \copydoc SparseMatrix::coeffRef */ inline Scalar& coeffRef(Index row, Index col) { const Index outer = IsRowMajor ? row : col; const Index inner = IsRowMajor ? col : row; Index start = Base::m_outerIndex[outer]; Index end = Base::isCompressed() ? Base::m_outerIndex[outer+1] : start + Base::m_innerNonZeros[outer]; eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix"); eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient"); StorageIndex* r = std::lower_bound(&Base::m_innerIndices[start],&Base::m_innerIndices[end],inner); const Index id = r - &Base::m_innerIndices[0]; eigen_assert((*r==inner) && (id(Base::m_values)[id]; } inline SparseMapBase(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr, Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0) : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) {} // for vectors inline SparseMapBase(Index size, Index nnz, StorageIndex* innerIndexPtr, Scalar* valuePtr) : Base(size, nnz, innerIndexPtr, valuePtr) {} /** Empty destructor */ inline ~SparseMapBase() {} protected: inline SparseMapBase() {} }; /** \ingroup SparseCore_Module * * \brief Specialization of class Map for SparseMatrix-like storage. * * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix. * * \sa class Map, class SparseMatrix, class Ref */ #ifndef EIGEN_PARSED_BY_DOXYGEN template class Map, Options, StrideType> : public SparseMapBase, Options, StrideType> > #else template class Map : public SparseMapBase #endif { public: typedef SparseMapBase Base; EIGEN_SPARSE_PUBLIC_INTERFACE(Map) enum { IsRowMajor = Base::IsRowMajor }; public: /** Constructs a read-write Map to a sparse matrix of size \a rows x \a cols, containing \a nnz non-zero coefficients, * stored as a sparse format as defined by the pointers \a outerIndexPtr, \a innerIndexPtr, and \a valuePtr. * If the optional parameter \a innerNonZerosPtr is the null pointer, then a standard compressed format is assumed. * * This constructor is available only if \c SparseMatrixType is non-const. * * More details on the expected storage schemes are given in the \ref TutorialSparse "manual pages". */ inline Map(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr, Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0) : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) {} #ifndef EIGEN_PARSED_BY_DOXYGEN /** Empty destructor */ inline ~Map() {} }; template class Map, Options, StrideType> : public SparseMapBase, Options, StrideType> > { public: typedef SparseMapBase Base; EIGEN_SPARSE_PUBLIC_INTERFACE(Map) enum { IsRowMajor = Base::IsRowMajor }; public: #endif /** This is the const version of the above constructor. * * This constructor is available only if \c SparseMatrixType is const, e.g.: * \code Map > \endcode */ inline Map(Index rows, Index cols, Index nnz, const StorageIndex* outerIndexPtr, const StorageIndex* innerIndexPtr, const Scalar* valuePtr, const StorageIndex* innerNonZerosPtr = 0) : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) {} /** Empty destructor */ inline ~Map() {} }; namespace internal { template struct evaluator, Options, StrideType> > : evaluator, Options, StrideType> > > { typedef evaluator, Options, StrideType> > > Base; typedef Map, Options, StrideType> XprType; evaluator() : Base() {} explicit evaluator(const XprType &mat) : Base(mat) {} }; template struct evaluator, Options, StrideType> > : evaluator, Options, StrideType> > > { typedef evaluator, Options, StrideType> > > Base; typedef Map, Options, StrideType> XprType; evaluator() : Base() {} explicit evaluator(const XprType &mat) : Base(mat) {} }; } } // end namespace Eigen #endif // EIGEN_SPARSE_MAP_H