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
13namespace Eigen {
14
15namespace internal {
16
17template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
18struct 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
28template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
29struct 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
41template<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 */
49template<typename Derived>
50class 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 */
147template<typename Derived>
148class 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
221template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
222class Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType>
223 : public SparseMapBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
224#else
225template<typename SparseMatrixType>
226class 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
254template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
255class 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
279namespace internal {
280
281template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
282struct 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
291template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
292struct 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