| 1 | // This file is part of Eigen, a lightweight C++ template library |
| 2 | // for linear algebra. |
| 3 | // |
| 4 | // Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr> |
| 5 | // |
| 6 | // This Source Code Form is subject to the terms of the Mozilla |
| 7 | // Public License v. 2.0. If a copy of the MPL was not distributed |
| 8 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 9 | |
| 10 | #ifndef EIGEN_SPARSE_MAP_H |
| 11 | #define EIGEN_SPARSE_MAP_H |
| 12 | |
| 13 | namespace Eigen { |
| 14 | |
| 15 | namespace internal { |
| 16 | |
| 17 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 18 | struct traits<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 19 | : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> > |
| 20 | { |
| 21 | typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; |
| 22 | typedef traits<PlainObjectType> TraitsBase; |
| 23 | enum { |
| 24 | Flags = TraitsBase::Flags & (~NestByRefBit) |
| 25 | }; |
| 26 | }; |
| 27 | |
| 28 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 29 | struct traits<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 30 | : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> > |
| 31 | { |
| 32 | typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; |
| 33 | typedef traits<PlainObjectType> TraitsBase; |
| 34 | enum { |
| 35 | Flags = TraitsBase::Flags & (~ (NestByRefBit | LvalueBit)) |
| 36 | }; |
| 37 | }; |
| 38 | |
| 39 | } // end namespace internal |
| 40 | |
| 41 | template<typename Derived, |
| 42 | int Level = internal::accessors_level<Derived>::has_write_access ? WriteAccessors : ReadOnlyAccessors |
| 43 | > class SparseMapBase; |
| 44 | |
| 45 | /** \ingroup SparseCore_Module |
| 46 | * class SparseMapBase |
| 47 | * \brief Common base class for Map and Ref instance of sparse matrix and vector. |
| 48 | */ |
| 49 | template<typename Derived> |
| 50 | class SparseMapBase<Derived,ReadOnlyAccessors> |
| 51 | : public SparseCompressedBase<Derived> |
| 52 | { |
| 53 | public: |
| 54 | typedef SparseCompressedBase<Derived> Base; |
| 55 | typedef typename Base::Scalar Scalar; |
| 56 | typedef typename Base::StorageIndex StorageIndex; |
| 57 | enum { IsRowMajor = Base::IsRowMajor }; |
| 58 | using Base::operator=; |
| 59 | protected: |
| 60 | |
| 61 | typedef typename internal::conditional< |
| 62 | bool(internal::is_lvalue<Derived>::value), |
| 63 | Scalar *, const Scalar *>::type ScalarPointer; |
| 64 | typedef typename internal::conditional< |
| 65 | bool(internal::is_lvalue<Derived>::value), |
| 66 | StorageIndex *, const StorageIndex *>::type IndexPointer; |
| 67 | |
| 68 | Index m_outerSize; |
| 69 | Index m_innerSize; |
| 70 | Array<StorageIndex,2,1> m_zero_nnz; |
| 71 | IndexPointer m_outerIndex; |
| 72 | IndexPointer m_innerIndices; |
| 73 | ScalarPointer m_values; |
| 74 | IndexPointer m_innerNonZeros; |
| 75 | |
| 76 | public: |
| 77 | |
| 78 | /** \copydoc SparseMatrixBase::rows() */ |
| 79 | inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; } |
| 80 | /** \copydoc SparseMatrixBase::cols() */ |
| 81 | inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; } |
| 82 | /** \copydoc SparseMatrixBase::innerSize() */ |
| 83 | inline Index innerSize() const { return m_innerSize; } |
| 84 | /** \copydoc SparseMatrixBase::outerSize() */ |
| 85 | inline Index outerSize() const { return m_outerSize; } |
| 86 | /** \copydoc SparseCompressedBase::nonZeros */ |
| 87 | inline Index nonZeros() const { return m_zero_nnz[1]; } |
| 88 | |
| 89 | /** \copydoc SparseCompressedBase::isCompressed */ |
| 90 | bool isCompressed() const { return m_innerNonZeros==0; } |
| 91 | |
| 92 | //---------------------------------------- |
| 93 | // direct access interface |
| 94 | /** \copydoc SparseMatrix::valuePtr */ |
| 95 | inline const Scalar* valuePtr() const { return m_values; } |
| 96 | /** \copydoc SparseMatrix::innerIndexPtr */ |
| 97 | inline const StorageIndex* innerIndexPtr() const { return m_innerIndices; } |
| 98 | /** \copydoc SparseMatrix::outerIndexPtr */ |
| 99 | inline const StorageIndex* outerIndexPtr() const { return m_outerIndex; } |
| 100 | /** \copydoc SparseMatrix::innerNonZeroPtr */ |
| 101 | inline const StorageIndex* innerNonZeroPtr() const { return m_innerNonZeros; } |
| 102 | //---------------------------------------- |
| 103 | |
| 104 | /** \copydoc SparseMatrix::coeff */ |
| 105 | inline Scalar coeff(Index row, Index col) const |
| 106 | { |
| 107 | const Index outer = IsRowMajor ? row : col; |
| 108 | const Index inner = IsRowMajor ? col : row; |
| 109 | |
| 110 | Index start = m_outerIndex[outer]; |
| 111 | Index end = isCompressed() ? m_outerIndex[outer+1] : start + m_innerNonZeros[outer]; |
| 112 | if (start==end) |
| 113 | return Scalar(0); |
| 114 | else if (end>0 && inner==m_innerIndices[end-1]) |
| 115 | return m_values[end-1]; |
| 116 | // ^^ optimization: let's first check if it is the last coefficient |
| 117 | // (very common in high level algorithms) |
| 118 | |
| 119 | const StorageIndex* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner); |
| 120 | const Index id = r-&m_innerIndices[0]; |
| 121 | return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0); |
| 122 | } |
| 123 | |
| 124 | inline SparseMapBase(Index rows, Index cols, Index nnz, IndexPointer outerIndexPtr, IndexPointer innerIndexPtr, |
| 125 | ScalarPointer valuePtr, IndexPointer innerNonZerosPtr = 0) |
| 126 | : m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_zero_nnz(0,internal::convert_index<StorageIndex>(nnz)), m_outerIndex(outerIndexPtr), |
| 127 | m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(innerNonZerosPtr) |
| 128 | {} |
| 129 | |
| 130 | // for vectors |
| 131 | inline SparseMapBase(Index size, Index nnz, IndexPointer innerIndexPtr, ScalarPointer valuePtr) |
| 132 | : m_outerSize(1), m_innerSize(size), m_zero_nnz(0,internal::convert_index<StorageIndex>(nnz)), m_outerIndex(m_zero_nnz.data()), |
| 133 | m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(0) |
| 134 | {} |
| 135 | |
| 136 | /** Empty destructor */ |
| 137 | inline ~SparseMapBase() {} |
| 138 | |
| 139 | protected: |
| 140 | inline SparseMapBase() {} |
| 141 | }; |
| 142 | |
| 143 | /** \ingroup SparseCore_Module |
| 144 | * class SparseMapBase |
| 145 | * \brief Common base class for writable Map and Ref instance of sparse matrix and vector. |
| 146 | */ |
| 147 | template<typename Derived> |
| 148 | class SparseMapBase<Derived,WriteAccessors> |
| 149 | : public SparseMapBase<Derived,ReadOnlyAccessors> |
| 150 | { |
| 151 | typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase; |
| 152 | |
| 153 | public: |
| 154 | typedef SparseMapBase<Derived, ReadOnlyAccessors> Base; |
| 155 | typedef typename Base::Scalar Scalar; |
| 156 | typedef typename Base::StorageIndex StorageIndex; |
| 157 | enum { IsRowMajor = Base::IsRowMajor }; |
| 158 | |
| 159 | using Base::operator=; |
| 160 | |
| 161 | public: |
| 162 | |
| 163 | //---------------------------------------- |
| 164 | // direct access interface |
| 165 | using Base::valuePtr; |
| 166 | using Base::innerIndexPtr; |
| 167 | using Base::outerIndexPtr; |
| 168 | using Base::innerNonZeroPtr; |
| 169 | /** \copydoc SparseMatrix::valuePtr */ |
| 170 | inline Scalar* valuePtr() { return Base::m_values; } |
| 171 | /** \copydoc SparseMatrix::innerIndexPtr */ |
| 172 | inline StorageIndex* innerIndexPtr() { return Base::m_innerIndices; } |
| 173 | /** \copydoc SparseMatrix::outerIndexPtr */ |
| 174 | inline StorageIndex* outerIndexPtr() { return Base::m_outerIndex; } |
| 175 | /** \copydoc SparseMatrix::innerNonZeroPtr */ |
| 176 | inline StorageIndex* innerNonZeroPtr() { return Base::m_innerNonZeros; } |
| 177 | //---------------------------------------- |
| 178 | |
| 179 | /** \copydoc SparseMatrix::coeffRef */ |
| 180 | inline Scalar& coeffRef(Index row, Index col) |
| 181 | { |
| 182 | const Index outer = IsRowMajor ? row : col; |
| 183 | const Index inner = IsRowMajor ? col : row; |
| 184 | |
| 185 | Index start = Base::m_outerIndex[outer]; |
| 186 | Index end = Base::isCompressed() ? Base::m_outerIndex[outer+1] : start + Base::m_innerNonZeros[outer]; |
| 187 | eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix" ); |
| 188 | eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient" ); |
| 189 | StorageIndex* r = std::lower_bound(&Base::m_innerIndices[start],&Base::m_innerIndices[end],inner); |
| 190 | const Index id = r - &Base::m_innerIndices[0]; |
| 191 | eigen_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient" ); |
| 192 | return const_cast<Scalar*>(Base::m_values)[id]; |
| 193 | } |
| 194 | |
| 195 | inline SparseMapBase(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr, |
| 196 | Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0) |
| 197 | : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) |
| 198 | {} |
| 199 | |
| 200 | // for vectors |
| 201 | inline SparseMapBase(Index size, Index nnz, StorageIndex* innerIndexPtr, Scalar* valuePtr) |
| 202 | : Base(size, nnz, innerIndexPtr, valuePtr) |
| 203 | {} |
| 204 | |
| 205 | /** Empty destructor */ |
| 206 | inline ~SparseMapBase() {} |
| 207 | |
| 208 | protected: |
| 209 | inline SparseMapBase() {} |
| 210 | }; |
| 211 | |
| 212 | /** \ingroup SparseCore_Module |
| 213 | * |
| 214 | * \brief Specialization of class Map for SparseMatrix-like storage. |
| 215 | * |
| 216 | * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix. |
| 217 | * |
| 218 | * \sa class Map, class SparseMatrix, class Ref<SparseMatrixType,Options> |
| 219 | */ |
| 220 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
| 221 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 222 | class Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> |
| 223 | : public SparseMapBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 224 | #else |
| 225 | template<typename SparseMatrixType> |
| 226 | class Map<SparseMatrixType> |
| 227 | : public SparseMapBase<Derived,WriteAccessors> |
| 228 | #endif |
| 229 | { |
| 230 | public: |
| 231 | typedef SparseMapBase<Map> Base; |
| 232 | EIGEN_SPARSE_PUBLIC_INTERFACE(Map) |
| 233 | enum { IsRowMajor = Base::IsRowMajor }; |
| 234 | |
| 235 | public: |
| 236 | |
| 237 | /** Constructs a read-write Map to a sparse matrix of size \a rows x \a cols, containing \a nnz non-zero coefficients, |
| 238 | * stored as a sparse format as defined by the pointers \a outerIndexPtr, \a innerIndexPtr, and \a valuePtr. |
| 239 | * If the optional parameter \a innerNonZerosPtr is the null pointer, then a standard compressed format is assumed. |
| 240 | * |
| 241 | * This constructor is available only if \c SparseMatrixType is non-const. |
| 242 | * |
| 243 | * More details on the expected storage schemes are given in the \ref TutorialSparse "manual pages". |
| 244 | */ |
| 245 | inline Map(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr, |
| 246 | StorageIndex* innerIndexPtr, Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0) |
| 247 | : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) |
| 248 | {} |
| 249 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
| 250 | /** Empty destructor */ |
| 251 | inline ~Map() {} |
| 252 | }; |
| 253 | |
| 254 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 255 | class Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> |
| 256 | : public SparseMapBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 257 | { |
| 258 | public: |
| 259 | typedef SparseMapBase<Map> Base; |
| 260 | EIGEN_SPARSE_PUBLIC_INTERFACE(Map) |
| 261 | enum { IsRowMajor = Base::IsRowMajor }; |
| 262 | |
| 263 | public: |
| 264 | #endif |
| 265 | /** This is the const version of the above constructor. |
| 266 | * |
| 267 | * This constructor is available only if \c SparseMatrixType is const, e.g.: |
| 268 | * \code Map<const SparseMatrix<double> > \endcode |
| 269 | */ |
| 270 | inline Map(Index rows, Index cols, Index nnz, const StorageIndex* outerIndexPtr, |
| 271 | const StorageIndex* innerIndexPtr, const Scalar* valuePtr, const StorageIndex* innerNonZerosPtr = 0) |
| 272 | : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr) |
| 273 | {} |
| 274 | |
| 275 | /** Empty destructor */ |
| 276 | inline ~Map() {} |
| 277 | }; |
| 278 | |
| 279 | namespace internal { |
| 280 | |
| 281 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 282 | struct evaluator<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 283 | : evaluator<SparseCompressedBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
| 284 | { |
| 285 | typedef evaluator<SparseCompressedBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
| 286 | typedef Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
| 287 | evaluator() : Base() {} |
| 288 | explicit evaluator(const XprType &mat) : Base(mat) {} |
| 289 | }; |
| 290 | |
| 291 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
| 292 | struct evaluator<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
| 293 | : evaluator<SparseCompressedBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
| 294 | { |
| 295 | typedef evaluator<SparseCompressedBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
| 296 | typedef Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
| 297 | evaluator() : Base() {} |
| 298 | explicit evaluator(const XprType &mat) : Base(mat) {} |
| 299 | }; |
| 300 | |
| 301 | } |
| 302 | |
| 303 | } // end namespace Eigen |
| 304 | |
| 305 | #endif // EIGEN_SPARSE_MAP_H |
| 306 | |