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 | |