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_REF_H |
11 | #define EIGEN_SPARSE_REF_H |
12 | |
13 | namespace Eigen { |
14 | |
15 | enum { |
16 | StandardCompressedFormat = 2 /**< used by Ref<SparseMatrix> to specify whether the input storage must be in standard compressed form */ |
17 | }; |
18 | |
19 | namespace internal { |
20 | |
21 | template<typename Derived> class SparseRefBase; |
22 | |
23 | template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> |
24 | struct traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
25 | : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> > |
26 | { |
27 | typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; |
28 | enum { |
29 | Options = _Options, |
30 | Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit |
31 | }; |
32 | |
33 | template<typename Derived> struct match { |
34 | enum { |
35 | StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)), |
36 | MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && StorageOrderMatch |
37 | }; |
38 | typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; |
39 | }; |
40 | |
41 | }; |
42 | |
43 | template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> |
44 | struct traits<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
45 | : public traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
46 | { |
47 | enum { |
48 | Flags = (traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit |
49 | }; |
50 | }; |
51 | |
52 | template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> |
53 | struct traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
54 | : public traits<SparseVector<MatScalar,MatOptions,MatIndex> > |
55 | { |
56 | typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType; |
57 | enum { |
58 | Options = _Options, |
59 | Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit |
60 | }; |
61 | |
62 | template<typename Derived> struct match { |
63 | enum { |
64 | MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && Derived::IsVectorAtCompileTime |
65 | }; |
66 | typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type; |
67 | }; |
68 | |
69 | }; |
70 | |
71 | template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType> |
72 | struct traits<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
73 | : public traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> > |
74 | { |
75 | enum { |
76 | Flags = (traits<SparseVector<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit |
77 | }; |
78 | }; |
79 | |
80 | template<typename Derived> |
81 | struct traits<SparseRefBase<Derived> > : public traits<Derived> {}; |
82 | |
83 | template<typename Derived> class SparseRefBase |
84 | : public SparseMapBase<Derived> |
85 | { |
86 | public: |
87 | |
88 | typedef SparseMapBase<Derived> Base; |
89 | EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase) |
90 | |
91 | SparseRefBase() |
92 | : Base(RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime, 0, 0, 0, 0, 0) |
93 | {} |
94 | |
95 | protected: |
96 | |
97 | template<typename Expression> |
98 | void construct(Expression& expr) |
99 | { |
100 | if(expr.outerIndexPtr()==0) |
101 | ::new (static_cast<Base*>(this)) Base(expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr()); |
102 | else |
103 | ::new (static_cast<Base*>(this)) Base(expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(), expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr()); |
104 | } |
105 | }; |
106 | |
107 | } // namespace internal |
108 | |
109 | |
110 | /** |
111 | * \ingroup SparseCore_Module |
112 | * |
113 | * \brief A sparse matrix expression referencing an existing sparse expression |
114 | * |
115 | * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix. |
116 | * \tparam Options specifies whether the a standard compressed format is required \c Options is \c #StandardCompressedFormat, or \c 0. |
117 | * The default is \c 0. |
118 | * |
119 | * \sa class Ref |
120 | */ |
121 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
122 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
123 | class Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType > |
124 | : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType > > |
125 | #else |
126 | template<typename SparseMatrixType, int Options> |
127 | class Ref<SparseMatrixType, Options> |
128 | : public SparseMapBase<Derived,WriteAccessors> // yes, that's weird to use Derived here, but that works! |
129 | #endif |
130 | { |
131 | typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType; |
132 | typedef internal::traits<Ref> Traits; |
133 | template<int OtherOptions> |
134 | inline Ref(const SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr); |
135 | template<int OtherOptions> |
136 | inline Ref(const MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr); |
137 | public: |
138 | |
139 | typedef internal::SparseRefBase<Ref> Base; |
140 | EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) |
141 | |
142 | |
143 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
144 | template<int OtherOptions> |
145 | inline Ref(SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr) |
146 | { |
147 | EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); |
148 | eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); |
149 | Base::construct(expr.derived()); |
150 | } |
151 | |
152 | template<int OtherOptions> |
153 | inline Ref(MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr) |
154 | { |
155 | EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); |
156 | eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); |
157 | Base::construct(expr.derived()); |
158 | } |
159 | |
160 | template<typename Derived> |
161 | inline Ref(const SparseCompressedBase<Derived>& expr) |
162 | #else |
163 | /** Implicit constructor from any sparse expression (2D matrix or 1D vector) */ |
164 | template<typename Derived> |
165 | inline Ref(SparseCompressedBase<Derived>& expr) |
166 | #endif |
167 | { |
168 | EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); |
169 | EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); |
170 | eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) ); |
171 | Base::construct(expr.const_cast_derived()); |
172 | } |
173 | }; |
174 | |
175 | // this is the const ref version |
176 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
177 | class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> |
178 | : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
179 | { |
180 | typedef SparseMatrix<MatScalar,MatOptions,MatIndex> TPlainObjectType; |
181 | typedef internal::traits<Ref> Traits; |
182 | public: |
183 | |
184 | typedef internal::SparseRefBase<Ref> Base; |
185 | EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) |
186 | |
187 | template<typename Derived> |
188 | inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) |
189 | { |
190 | construct(expr.derived(), typename Traits::template match<Derived>::type()); |
191 | } |
192 | |
193 | inline Ref(const Ref& other) : Base(other), m_hasCopy(false) { |
194 | // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy |
195 | } |
196 | |
197 | template<typename OtherRef> |
198 | inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) { |
199 | construct(other.derived(), typename Traits::template match<OtherRef>::type()); |
200 | } |
201 | |
202 | ~Ref() { |
203 | if(m_hasCopy) { |
204 | TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); |
205 | obj->~TPlainObjectType(); |
206 | } |
207 | } |
208 | |
209 | protected: |
210 | |
211 | template<typename Expression> |
212 | void construct(const Expression& expr,internal::true_type) |
213 | { |
214 | if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) |
215 | { |
216 | TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); |
217 | ::new (obj) TPlainObjectType(expr); |
218 | m_hasCopy = true; |
219 | Base::construct(*obj); |
220 | } |
221 | else |
222 | { |
223 | Base::construct(expr); |
224 | } |
225 | } |
226 | |
227 | template<typename Expression> |
228 | void construct(const Expression& expr, internal::false_type) |
229 | { |
230 | TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); |
231 | ::new (obj) TPlainObjectType(expr); |
232 | m_hasCopy = true; |
233 | Base::construct(*obj); |
234 | } |
235 | |
236 | protected: |
237 | char m_object_bytes[sizeof(TPlainObjectType)]; |
238 | bool m_hasCopy; |
239 | }; |
240 | |
241 | |
242 | |
243 | /** |
244 | * \ingroup SparseCore_Module |
245 | * |
246 | * \brief A sparse vector expression referencing an existing sparse vector expression |
247 | * |
248 | * \tparam SparseVectorType the equivalent sparse vector type of the referenced data, it must be a template instance of class SparseVector. |
249 | * |
250 | * \sa class Ref |
251 | */ |
252 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
253 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
254 | class Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType > |
255 | : public internal::SparseRefBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType > > |
256 | #else |
257 | template<typename SparseVectorType> |
258 | class Ref<SparseVectorType> |
259 | : public SparseMapBase<Derived,WriteAccessors> |
260 | #endif |
261 | { |
262 | typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType; |
263 | typedef internal::traits<Ref> Traits; |
264 | template<int OtherOptions> |
265 | inline Ref(const SparseVector<MatScalar,OtherOptions,MatIndex>& expr); |
266 | public: |
267 | |
268 | typedef internal::SparseRefBase<Ref> Base; |
269 | EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) |
270 | |
271 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
272 | template<int OtherOptions> |
273 | inline Ref(SparseVector<MatScalar,OtherOptions,MatIndex>& expr) |
274 | { |
275 | EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseVector<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); |
276 | Base::construct(expr.derived()); |
277 | } |
278 | |
279 | template<typename Derived> |
280 | inline Ref(const SparseCompressedBase<Derived>& expr) |
281 | #else |
282 | /** Implicit constructor from any 1D sparse vector expression */ |
283 | template<typename Derived> |
284 | inline Ref(SparseCompressedBase<Derived>& expr) |
285 | #endif |
286 | { |
287 | EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY); |
288 | EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH); |
289 | Base::construct(expr.const_cast_derived()); |
290 | } |
291 | }; |
292 | |
293 | // this is the const ref version |
294 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
295 | class Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> |
296 | : public internal::SparseRefBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
297 | { |
298 | typedef SparseVector<MatScalar,MatOptions,MatIndex> TPlainObjectType; |
299 | typedef internal::traits<Ref> Traits; |
300 | public: |
301 | |
302 | typedef internal::SparseRefBase<Ref> Base; |
303 | EIGEN_SPARSE_PUBLIC_INTERFACE(Ref) |
304 | |
305 | template<typename Derived> |
306 | inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) |
307 | { |
308 | construct(expr.derived(), typename Traits::template match<Derived>::type()); |
309 | } |
310 | |
311 | inline Ref(const Ref& other) : Base(other), m_hasCopy(false) { |
312 | // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy |
313 | } |
314 | |
315 | template<typename OtherRef> |
316 | inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) { |
317 | construct(other.derived(), typename Traits::template match<OtherRef>::type()); |
318 | } |
319 | |
320 | ~Ref() { |
321 | if(m_hasCopy) { |
322 | TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); |
323 | obj->~TPlainObjectType(); |
324 | } |
325 | } |
326 | |
327 | protected: |
328 | |
329 | template<typename Expression> |
330 | void construct(const Expression& expr,internal::true_type) |
331 | { |
332 | Base::construct(expr); |
333 | } |
334 | |
335 | template<typename Expression> |
336 | void construct(const Expression& expr, internal::false_type) |
337 | { |
338 | TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes); |
339 | ::new (obj) TPlainObjectType(expr); |
340 | m_hasCopy = true; |
341 | Base::construct(*obj); |
342 | } |
343 | |
344 | protected: |
345 | char m_object_bytes[sizeof(TPlainObjectType)]; |
346 | bool m_hasCopy; |
347 | }; |
348 | |
349 | namespace internal { |
350 | |
351 | // FIXME shall we introduce a general evaluatior_ref that we can specialize for any sparse object once, and thus remove this copy-pasta thing... |
352 | |
353 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
354 | struct evaluator<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
355 | : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
356 | { |
357 | typedef evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
358 | typedef Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
359 | evaluator() : Base() {} |
360 | explicit evaluator(const XprType &mat) : Base(mat) {} |
361 | }; |
362 | |
363 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
364 | struct evaluator<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
365 | : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
366 | { |
367 | typedef evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
368 | typedef Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
369 | evaluator() : Base() {} |
370 | explicit evaluator(const XprType &mat) : Base(mat) {} |
371 | }; |
372 | |
373 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
374 | struct evaluator<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
375 | : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
376 | { |
377 | typedef evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
378 | typedef Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
379 | evaluator() : Base() {} |
380 | explicit evaluator(const XprType &mat) : Base(mat) {} |
381 | }; |
382 | |
383 | template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType> |
384 | struct evaluator<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > |
385 | : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > |
386 | { |
387 | typedef evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base; |
388 | typedef Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType; |
389 | evaluator() : Base() {} |
390 | explicit evaluator(const XprType &mat) : Base(mat) {} |
391 | }; |
392 | |
393 | } |
394 | |
395 | } // end namespace Eigen |
396 | |
397 | #endif // EIGEN_SPARSE_REF_H |
398 | |