1 | // This file is part of Eigen, a lightweight C++ template library |
2 | // for linear algebra. |
3 | // |
4 | // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
5 | // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
6 | // |
7 | // This Source Code Form is subject to the terms of the Mozilla |
8 | // Public License v. 2.0. If a copy of the MPL was not distributed |
9 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
10 | |
11 | #ifndef EIGEN_DENSESTORAGEBASE_H |
12 | #define EIGEN_DENSESTORAGEBASE_H |
13 | |
14 | #if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO) |
15 | # define EIGEN_INITIALIZE_COEFFS |
16 | # define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0); |
17 | #elif defined(EIGEN_INITIALIZE_MATRICES_BY_NAN) |
18 | # define EIGEN_INITIALIZE_COEFFS |
19 | # define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=std::numeric_limits<Scalar>::quiet_NaN(); |
20 | #else |
21 | # undef EIGEN_INITIALIZE_COEFFS |
22 | # define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
23 | #endif |
24 | |
25 | namespace Eigen { |
26 | |
27 | namespace internal { |
28 | |
29 | template<int MaxSizeAtCompileTime> struct check_rows_cols_for_overflow { |
30 | template<typename Index> |
31 | EIGEN_DEVICE_FUNC |
32 | static EIGEN_ALWAYS_INLINE void run(Index, Index) |
33 | { |
34 | } |
35 | }; |
36 | |
37 | template<> struct check_rows_cols_for_overflow<Dynamic> { |
38 | template<typename Index> |
39 | EIGEN_DEVICE_FUNC |
40 | static EIGEN_ALWAYS_INLINE void run(Index rows, Index cols) |
41 | { |
42 | // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 |
43 | // we assume Index is signed |
44 | Index max_index = (std::size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed |
45 | bool error = (rows == 0 || cols == 0) ? false |
46 | : (rows > max_index / cols); |
47 | if (error) |
48 | throw_std_bad_alloc(); |
49 | } |
50 | }; |
51 | |
52 | template <typename Derived, |
53 | typename OtherDerived = Derived, |
54 | bool IsVector = bool(Derived::IsVectorAtCompileTime) && bool(OtherDerived::IsVectorAtCompileTime)> |
55 | struct conservative_resize_like_impl; |
56 | |
57 | template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl; |
58 | |
59 | } // end namespace internal |
60 | |
61 | #ifdef EIGEN_PARSED_BY_DOXYGEN |
62 | namespace doxygen { |
63 | |
64 | // This is a workaround to doxygen not being able to understand the inheritance logic |
65 | // when it is hidden by the dense_xpr_base helper struct. |
66 | // Moreover, doxygen fails to include members that are not documented in the declaration body of |
67 | // MatrixBase if we inherits MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >, |
68 | // this is why we simply inherits MatrixBase, though this does not make sense. |
69 | |
70 | /** This class is just a workaround for Doxygen and it does not not actually exist. */ |
71 | template<typename Derived> struct dense_xpr_base_dispatcher; |
72 | /** This class is just a workaround for Doxygen and it does not not actually exist. */ |
73 | template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
74 | struct dense_xpr_base_dispatcher<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
75 | : public MatrixBase {}; |
76 | /** This class is just a workaround for Doxygen and it does not not actually exist. */ |
77 | template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
78 | struct dense_xpr_base_dispatcher<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
79 | : public ArrayBase {}; |
80 | |
81 | } // namespace doxygen |
82 | |
83 | /** \class PlainObjectBase |
84 | * \ingroup Core_Module |
85 | * \brief %Dense storage base class for matrices and arrays. |
86 | * |
87 | * This class can be extended with the help of the plugin mechanism described on the page |
88 | * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN. |
89 | * |
90 | * \tparam Derived is the derived type, e.g., a Matrix or Array |
91 | * |
92 | * \sa \ref TopicClassHierarchy |
93 | */ |
94 | template<typename Derived> |
95 | class PlainObjectBase : public doxygen::dense_xpr_base_dispatcher<Derived> |
96 | #else |
97 | template<typename Derived> |
98 | class PlainObjectBase : public internal::dense_xpr_base<Derived>::type |
99 | #endif |
100 | { |
101 | public: |
102 | enum { Options = internal::traits<Derived>::Options }; |
103 | typedef typename internal::dense_xpr_base<Derived>::type Base; |
104 | |
105 | typedef typename internal::traits<Derived>::StorageKind StorageKind; |
106 | typedef typename internal::traits<Derived>::Scalar Scalar; |
107 | |
108 | typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
109 | typedef typename NumTraits<Scalar>::Real RealScalar; |
110 | typedef Derived DenseType; |
111 | |
112 | using Base::RowsAtCompileTime; |
113 | using Base::ColsAtCompileTime; |
114 | using Base::SizeAtCompileTime; |
115 | using Base::MaxRowsAtCompileTime; |
116 | using Base::MaxColsAtCompileTime; |
117 | using Base::MaxSizeAtCompileTime; |
118 | using Base::IsVectorAtCompileTime; |
119 | using Base::Flags; |
120 | |
121 | template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map; |
122 | friend class Eigen::Map<Derived, Unaligned>; |
123 | typedef Eigen::Map<Derived, Unaligned> MapType; |
124 | friend class Eigen::Map<const Derived, Unaligned>; |
125 | typedef const Eigen::Map<const Derived, Unaligned> ConstMapType; |
126 | #if EIGEN_MAX_ALIGN_BYTES>0 |
127 | // for EIGEN_MAX_ALIGN_BYTES==0, AlignedMax==Unaligned, and many compilers generate warnings for friend-ing a class twice. |
128 | friend class Eigen::Map<Derived, AlignedMax>; |
129 | friend class Eigen::Map<const Derived, AlignedMax>; |
130 | #endif |
131 | typedef Eigen::Map<Derived, AlignedMax> AlignedMapType; |
132 | typedef const Eigen::Map<const Derived, AlignedMax> ConstAlignedMapType; |
133 | template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; }; |
134 | template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; }; |
135 | template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, AlignedMax, StrideType> type; }; |
136 | template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, AlignedMax, StrideType> type; }; |
137 | |
138 | protected: |
139 | DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage; |
140 | |
141 | public: |
142 | enum { NeedsToAlign = (SizeAtCompileTime != Dynamic) && (internal::traits<Derived>::Alignment>0) }; |
143 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) |
144 | |
145 | EIGEN_DEVICE_FUNC |
146 | Base& base() { return *static_cast<Base*>(this); } |
147 | EIGEN_DEVICE_FUNC |
148 | const Base& base() const { return *static_cast<const Base*>(this); } |
149 | |
150 | EIGEN_DEVICE_FUNC |
151 | EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); } |
152 | EIGEN_DEVICE_FUNC |
153 | EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); } |
154 | |
155 | /** This is an overloaded version of DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index,Index) const |
156 | * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. |
157 | * |
158 | * See DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index) const for details. */ |
159 | EIGEN_DEVICE_FUNC |
160 | EIGEN_STRONG_INLINE const Scalar& coeff(Index rowId, Index colId) const |
161 | { |
162 | if(Flags & RowMajorBit) |
163 | return m_storage.data()[colId + rowId * m_storage.cols()]; |
164 | else // column-major |
165 | return m_storage.data()[rowId + colId * m_storage.rows()]; |
166 | } |
167 | |
168 | /** This is an overloaded version of DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index) const |
169 | * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. |
170 | * |
171 | * See DenseCoeffsBase<Derived,ReadOnlyAccessors>::coeff(Index) const for details. */ |
172 | EIGEN_DEVICE_FUNC |
173 | EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const |
174 | { |
175 | return m_storage.data()[index]; |
176 | } |
177 | |
178 | /** This is an overloaded version of DenseCoeffsBase<Derived,WriteAccessors>::coeffRef(Index,Index) const |
179 | * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. |
180 | * |
181 | * See DenseCoeffsBase<Derived,WriteAccessors>::coeffRef(Index,Index) const for details. */ |
182 | EIGEN_DEVICE_FUNC |
183 | EIGEN_STRONG_INLINE Scalar& coeffRef(Index rowId, Index colId) |
184 | { |
185 | if(Flags & RowMajorBit) |
186 | return m_storage.data()[colId + rowId * m_storage.cols()]; |
187 | else // column-major |
188 | return m_storage.data()[rowId + colId * m_storage.rows()]; |
189 | } |
190 | |
191 | /** This is an overloaded version of DenseCoeffsBase<Derived,WriteAccessors>::coeffRef(Index) const |
192 | * provided to by-pass the creation of an evaluator of the expression, thus saving compilation efforts. |
193 | * |
194 | * See DenseCoeffsBase<Derived,WriteAccessors>::coeffRef(Index) const for details. */ |
195 | EIGEN_DEVICE_FUNC |
196 | EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) |
197 | { |
198 | return m_storage.data()[index]; |
199 | } |
200 | |
201 | /** This is the const version of coeffRef(Index,Index) which is thus synonym of coeff(Index,Index). |
202 | * It is provided for convenience. */ |
203 | EIGEN_DEVICE_FUNC |
204 | EIGEN_STRONG_INLINE const Scalar& coeffRef(Index rowId, Index colId) const |
205 | { |
206 | if(Flags & RowMajorBit) |
207 | return m_storage.data()[colId + rowId * m_storage.cols()]; |
208 | else // column-major |
209 | return m_storage.data()[rowId + colId * m_storage.rows()]; |
210 | } |
211 | |
212 | /** This is the const version of coeffRef(Index) which is thus synonym of coeff(Index). |
213 | * It is provided for convenience. */ |
214 | EIGEN_DEVICE_FUNC |
215 | EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const |
216 | { |
217 | return m_storage.data()[index]; |
218 | } |
219 | |
220 | /** \internal */ |
221 | template<int LoadMode> |
222 | EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const |
223 | { |
224 | return internal::ploadt<PacketScalar, LoadMode> |
225 | (m_storage.data() + (Flags & RowMajorBit |
226 | ? colId + rowId * m_storage.cols() |
227 | : rowId + colId * m_storage.rows())); |
228 | } |
229 | |
230 | /** \internal */ |
231 | template<int LoadMode> |
232 | EIGEN_STRONG_INLINE PacketScalar packet(Index index) const |
233 | { |
234 | return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index); |
235 | } |
236 | |
237 | /** \internal */ |
238 | template<int StoreMode> |
239 | EIGEN_STRONG_INLINE void writePacket(Index rowId, Index colId, const PacketScalar& val) |
240 | { |
241 | internal::pstoret<Scalar, PacketScalar, StoreMode> |
242 | (m_storage.data() + (Flags & RowMajorBit |
243 | ? colId + rowId * m_storage.cols() |
244 | : rowId + colId * m_storage.rows()), val); |
245 | } |
246 | |
247 | /** \internal */ |
248 | template<int StoreMode> |
249 | EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& val) |
250 | { |
251 | internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, val); |
252 | } |
253 | |
254 | /** \returns a const pointer to the data array of this matrix */ |
255 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar *data() const |
256 | { return m_storage.data(); } |
257 | |
258 | /** \returns a pointer to the data array of this matrix */ |
259 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar *data() |
260 | { return m_storage.data(); } |
261 | |
262 | /** Resizes \c *this to a \a rows x \a cols matrix. |
263 | * |
264 | * This method is intended for dynamic-size matrices, although it is legal to call it on any |
265 | * matrix as long as fixed dimensions are left unchanged. If you only want to change the number |
266 | * of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t). |
267 | * |
268 | * If the current number of coefficients of \c *this exactly matches the |
269 | * product \a rows * \a cols, then no memory allocation is performed and |
270 | * the current values are left unchanged. In all other cases, including |
271 | * shrinking, the data is reallocated and all previous values are lost. |
272 | * |
273 | * Example: \include Matrix_resize_int_int.cpp |
274 | * Output: \verbinclude Matrix_resize_int_int.out |
275 | * |
276 | * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t) |
277 | */ |
278 | EIGEN_DEVICE_FUNC |
279 | EIGEN_STRONG_INLINE void resize(Index rows, Index cols) |
280 | { |
281 | eigen_assert( EIGEN_IMPLIES(RowsAtCompileTime!=Dynamic,rows==RowsAtCompileTime) |
282 | && EIGEN_IMPLIES(ColsAtCompileTime!=Dynamic,cols==ColsAtCompileTime) |
283 | && EIGEN_IMPLIES(RowsAtCompileTime==Dynamic && MaxRowsAtCompileTime!=Dynamic,rows<=MaxRowsAtCompileTime) |
284 | && EIGEN_IMPLIES(ColsAtCompileTime==Dynamic && MaxColsAtCompileTime!=Dynamic,cols<=MaxColsAtCompileTime) |
285 | && rows>=0 && cols>=0 && "Invalid sizes when resizing a matrix or array." ); |
286 | internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(rows, cols); |
287 | #ifdef EIGEN_INITIALIZE_COEFFS |
288 | Index size = rows*cols; |
289 | bool size_changed = size != this->size(); |
290 | m_storage.resize(size, rows, cols); |
291 | if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
292 | #else |
293 | m_storage.resize(rows*cols, rows, cols); |
294 | #endif |
295 | } |
296 | |
297 | /** Resizes \c *this to a vector of length \a size |
298 | * |
299 | * \only_for_vectors. This method does not work for |
300 | * partially dynamic matrices when the static dimension is anything other |
301 | * than 1. For example it will not work with Matrix<double, 2, Dynamic>. |
302 | * |
303 | * Example: \include Matrix_resize_int.cpp |
304 | * Output: \verbinclude Matrix_resize_int.out |
305 | * |
306 | * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t) |
307 | */ |
308 | EIGEN_DEVICE_FUNC |
309 | inline void resize(Index size) |
310 | { |
311 | EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase) |
312 | eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0); |
313 | #ifdef EIGEN_INITIALIZE_COEFFS |
314 | bool size_changed = size != this->size(); |
315 | #endif |
316 | if(RowsAtCompileTime == 1) |
317 | m_storage.resize(size, 1, size); |
318 | else |
319 | m_storage.resize(size, size, 1); |
320 | #ifdef EIGEN_INITIALIZE_COEFFS |
321 | if(size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
322 | #endif |
323 | } |
324 | |
325 | /** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the special value \c NoChange |
326 | * as in the example below. |
327 | * |
328 | * Example: \include Matrix_resize_NoChange_int.cpp |
329 | * Output: \verbinclude Matrix_resize_NoChange_int.out |
330 | * |
331 | * \sa resize(Index,Index) |
332 | */ |
333 | EIGEN_DEVICE_FUNC |
334 | inline void resize(NoChange_t, Index cols) |
335 | { |
336 | resize(rows(), cols); |
337 | } |
338 | |
339 | /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange |
340 | * as in the example below. |
341 | * |
342 | * Example: \include Matrix_resize_int_NoChange.cpp |
343 | * Output: \verbinclude Matrix_resize_int_NoChange.out |
344 | * |
345 | * \sa resize(Index,Index) |
346 | */ |
347 | EIGEN_DEVICE_FUNC |
348 | inline void resize(Index rows, NoChange_t) |
349 | { |
350 | resize(rows, cols()); |
351 | } |
352 | |
353 | /** Resizes \c *this to have the same dimensions as \a other. |
354 | * Takes care of doing all the checking that's needed. |
355 | * |
356 | * Note that copying a row-vector into a vector (and conversely) is allowed. |
357 | * The resizing, if any, is then done in the appropriate way so that row-vectors |
358 | * remain row-vectors and vectors remain vectors. |
359 | */ |
360 | template<typename OtherDerived> |
361 | EIGEN_DEVICE_FUNC |
362 | EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other) |
363 | { |
364 | const OtherDerived& other = _other.derived(); |
365 | internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime>::run(other.rows(), other.cols()); |
366 | const Index othersize = other.rows()*other.cols(); |
367 | if(RowsAtCompileTime == 1) |
368 | { |
369 | eigen_assert(other.rows() == 1 || other.cols() == 1); |
370 | resize(1, othersize); |
371 | } |
372 | else if(ColsAtCompileTime == 1) |
373 | { |
374 | eigen_assert(other.rows() == 1 || other.cols() == 1); |
375 | resize(othersize, 1); |
376 | } |
377 | else resize(other.rows(), other.cols()); |
378 | } |
379 | |
380 | /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
381 | * |
382 | * The method is intended for matrices of dynamic size. If you only want to change the number |
383 | * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or |
384 | * conservativeResize(Index, NoChange_t). |
385 | * |
386 | * Matrices are resized relative to the top-left element. In case values need to be |
387 | * appended to the matrix they will be uninitialized. |
388 | */ |
389 | EIGEN_DEVICE_FUNC |
390 | EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols) |
391 | { |
392 | internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols); |
393 | } |
394 | |
395 | /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
396 | * |
397 | * As opposed to conservativeResize(Index rows, Index cols), this version leaves |
398 | * the number of columns unchanged. |
399 | * |
400 | * In case the matrix is growing, new rows will be uninitialized. |
401 | */ |
402 | EIGEN_DEVICE_FUNC |
403 | EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t) |
404 | { |
405 | // Note: see the comment in conservativeResize(Index,Index) |
406 | conservativeResize(rows, cols()); |
407 | } |
408 | |
409 | /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
410 | * |
411 | * As opposed to conservativeResize(Index rows, Index cols), this version leaves |
412 | * the number of rows unchanged. |
413 | * |
414 | * In case the matrix is growing, new columns will be uninitialized. |
415 | */ |
416 | EIGEN_DEVICE_FUNC |
417 | EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols) |
418 | { |
419 | // Note: see the comment in conservativeResize(Index,Index) |
420 | conservativeResize(rows(), cols); |
421 | } |
422 | |
423 | /** Resizes the vector to \a size while retaining old values. |
424 | * |
425 | * \only_for_vectors. This method does not work for |
426 | * partially dynamic matrices when the static dimension is anything other |
427 | * than 1. For example it will not work with Matrix<double, 2, Dynamic>. |
428 | * |
429 | * When values are appended, they will be uninitialized. |
430 | */ |
431 | EIGEN_DEVICE_FUNC |
432 | EIGEN_STRONG_INLINE void conservativeResize(Index size) |
433 | { |
434 | internal::conservative_resize_like_impl<Derived>::run(*this, size); |
435 | } |
436 | |
437 | /** Resizes the matrix to \a rows x \a cols of \c other, while leaving old values untouched. |
438 | * |
439 | * The method is intended for matrices of dynamic size. If you only want to change the number |
440 | * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or |
441 | * conservativeResize(Index, NoChange_t). |
442 | * |
443 | * Matrices are resized relative to the top-left element. In case values need to be |
444 | * appended to the matrix they will copied from \c other. |
445 | */ |
446 | template<typename OtherDerived> |
447 | EIGEN_DEVICE_FUNC |
448 | EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other) |
449 | { |
450 | internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other); |
451 | } |
452 | |
453 | /** This is a special case of the templated operator=. Its purpose is to |
454 | * prevent a default operator= from hiding the templated operator=. |
455 | */ |
456 | EIGEN_DEVICE_FUNC |
457 | EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other) |
458 | { |
459 | return _set(other); |
460 | } |
461 | |
462 | /** \sa MatrixBase::lazyAssign() */ |
463 | template<typename OtherDerived> |
464 | EIGEN_DEVICE_FUNC |
465 | EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other) |
466 | { |
467 | _resize_to_match(other); |
468 | return Base::lazyAssign(other.derived()); |
469 | } |
470 | |
471 | template<typename OtherDerived> |
472 | EIGEN_DEVICE_FUNC |
473 | EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func) |
474 | { |
475 | resize(func.rows(), func.cols()); |
476 | return Base::operator=(func); |
477 | } |
478 | |
479 | // Prevent user from trying to instantiate PlainObjectBase objects |
480 | // by making all its constructor protected. See bug 1074. |
481 | protected: |
482 | |
483 | EIGEN_DEVICE_FUNC |
484 | EIGEN_STRONG_INLINE PlainObjectBase() : m_storage() |
485 | { |
486 | // _check_template_params(); |
487 | // EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
488 | } |
489 | |
490 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
491 | // FIXME is it still needed ? |
492 | /** \internal */ |
493 | EIGEN_DEVICE_FUNC |
494 | explicit PlainObjectBase(internal::constructor_without_unaligned_array_assert) |
495 | : m_storage(internal::constructor_without_unaligned_array_assert()) |
496 | { |
497 | // _check_template_params(); EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
498 | } |
499 | #endif |
500 | |
501 | #if EIGEN_HAS_RVALUE_REFERENCES |
502 | EIGEN_DEVICE_FUNC |
503 | PlainObjectBase(PlainObjectBase&& other) EIGEN_NOEXCEPT |
504 | : m_storage( std::move(other.m_storage) ) |
505 | { |
506 | } |
507 | |
508 | EIGEN_DEVICE_FUNC |
509 | PlainObjectBase& operator=(PlainObjectBase&& other) EIGEN_NOEXCEPT |
510 | { |
511 | using std::swap; |
512 | swap(m_storage, other.m_storage); |
513 | return *this; |
514 | } |
515 | #endif |
516 | |
517 | /** Copy constructor */ |
518 | EIGEN_DEVICE_FUNC |
519 | EIGEN_STRONG_INLINE PlainObjectBase(const PlainObjectBase& other) |
520 | : Base(), m_storage(other.m_storage) { } |
521 | EIGEN_DEVICE_FUNC |
522 | EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols) |
523 | : m_storage(size, rows, cols) |
524 | { |
525 | // _check_template_params(); |
526 | // EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED |
527 | } |
528 | |
529 | /** \sa PlainObjectBase::operator=(const EigenBase<OtherDerived>&) */ |
530 | template<typename OtherDerived> |
531 | EIGEN_DEVICE_FUNC |
532 | EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase<OtherDerived> &other) |
533 | : m_storage() |
534 | { |
535 | _check_template_params(); |
536 | resizeLike(other); |
537 | _set_noalias(other); |
538 | } |
539 | |
540 | /** \sa PlainObjectBase::operator=(const EigenBase<OtherDerived>&) */ |
541 | template<typename OtherDerived> |
542 | EIGEN_DEVICE_FUNC |
543 | EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other) |
544 | : m_storage() |
545 | { |
546 | _check_template_params(); |
547 | resizeLike(other); |
548 | *this = other.derived(); |
549 | } |
550 | /** \brief Copy constructor with in-place evaluation */ |
551 | template<typename OtherDerived> |
552 | EIGEN_DEVICE_FUNC |
553 | EIGEN_STRONG_INLINE PlainObjectBase(const ReturnByValue<OtherDerived>& other) |
554 | { |
555 | _check_template_params(); |
556 | // FIXME this does not automatically transpose vectors if necessary |
557 | resize(other.rows(), other.cols()); |
558 | other.evalTo(this->derived()); |
559 | } |
560 | |
561 | public: |
562 | |
563 | /** \brief Copies the generic expression \a other into *this. |
564 | * \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other) |
565 | */ |
566 | template<typename OtherDerived> |
567 | EIGEN_DEVICE_FUNC |
568 | EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other) |
569 | { |
570 | _resize_to_match(other); |
571 | Base::operator=(other.derived()); |
572 | return this->derived(); |
573 | } |
574 | |
575 | /** \name Map |
576 | * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects, |
577 | * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned |
578 | * \a data pointers. |
579 | * |
580 | * Here is an example using strides: |
581 | * \include Matrix_Map_stride.cpp |
582 | * Output: \verbinclude Matrix_Map_stride.out |
583 | * |
584 | * \see class Map |
585 | */ |
586 | //@{ |
587 | static inline ConstMapType Map(const Scalar* data) |
588 | { return ConstMapType(data); } |
589 | static inline MapType Map(Scalar* data) |
590 | { return MapType(data); } |
591 | static inline ConstMapType Map(const Scalar* data, Index size) |
592 | { return ConstMapType(data, size); } |
593 | static inline MapType Map(Scalar* data, Index size) |
594 | { return MapType(data, size); } |
595 | static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) |
596 | { return ConstMapType(data, rows, cols); } |
597 | static inline MapType Map(Scalar* data, Index rows, Index cols) |
598 | { return MapType(data, rows, cols); } |
599 | |
600 | static inline ConstAlignedMapType MapAligned(const Scalar* data) |
601 | { return ConstAlignedMapType(data); } |
602 | static inline AlignedMapType MapAligned(Scalar* data) |
603 | { return AlignedMapType(data); } |
604 | static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) |
605 | { return ConstAlignedMapType(data, size); } |
606 | static inline AlignedMapType MapAligned(Scalar* data, Index size) |
607 | { return AlignedMapType(data, size); } |
608 | static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) |
609 | { return ConstAlignedMapType(data, rows, cols); } |
610 | static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) |
611 | { return AlignedMapType(data, rows, cols); } |
612 | |
613 | template<int Outer, int Inner> |
614 | static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride) |
615 | { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); } |
616 | template<int Outer, int Inner> |
617 | static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride) |
618 | { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); } |
619 | template<int Outer, int Inner> |
620 | static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
621 | { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
622 | template<int Outer, int Inner> |
623 | static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
624 | { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
625 | template<int Outer, int Inner> |
626 | static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
627 | { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
628 | template<int Outer, int Inner> |
629 | static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
630 | { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
631 | |
632 | template<int Outer, int Inner> |
633 | static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride) |
634 | { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } |
635 | template<int Outer, int Inner> |
636 | static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride) |
637 | { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } |
638 | template<int Outer, int Inner> |
639 | static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
640 | { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
641 | template<int Outer, int Inner> |
642 | static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
643 | { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
644 | template<int Outer, int Inner> |
645 | static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
646 | { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
647 | template<int Outer, int Inner> |
648 | static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
649 | { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
650 | //@} |
651 | |
652 | using Base::setConstant; |
653 | EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& val); |
654 | EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& val); |
655 | |
656 | using Base::setZero; |
657 | EIGEN_DEVICE_FUNC Derived& setZero(Index size); |
658 | EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols); |
659 | |
660 | using Base::setOnes; |
661 | EIGEN_DEVICE_FUNC Derived& setOnes(Index size); |
662 | EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols); |
663 | |
664 | using Base::setRandom; |
665 | Derived& setRandom(Index size); |
666 | Derived& setRandom(Index rows, Index cols); |
667 | |
668 | #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN |
669 | #include EIGEN_PLAINOBJECTBASE_PLUGIN |
670 | #endif |
671 | |
672 | protected: |
673 | /** \internal Resizes *this in preparation for assigning \a other to it. |
674 | * Takes care of doing all the checking that's needed. |
675 | * |
676 | * Note that copying a row-vector into a vector (and conversely) is allowed. |
677 | * The resizing, if any, is then done in the appropriate way so that row-vectors |
678 | * remain row-vectors and vectors remain vectors. |
679 | */ |
680 | template<typename OtherDerived> |
681 | EIGEN_DEVICE_FUNC |
682 | EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) |
683 | { |
684 | #ifdef EIGEN_NO_AUTOMATIC_RESIZING |
685 | eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size()) |
686 | : (rows() == other.rows() && cols() == other.cols()))) |
687 | && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined" ); |
688 | EIGEN_ONLY_USED_FOR_DEBUG(other); |
689 | #else |
690 | resizeLike(other); |
691 | #endif |
692 | } |
693 | |
694 | /** |
695 | * \brief Copies the value of the expression \a other into \c *this with automatic resizing. |
696 | * |
697 | * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), |
698 | * it will be initialized. |
699 | * |
700 | * Note that copying a row-vector into a vector (and conversely) is allowed. |
701 | * The resizing, if any, is then done in the appropriate way so that row-vectors |
702 | * remain row-vectors and vectors remain vectors. |
703 | * |
704 | * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias() |
705 | * |
706 | * \internal |
707 | */ |
708 | // aliasing is dealt once in internall::call_assignment |
709 | // so at this stage we have to assume aliasing... and resising has to be done later. |
710 | template<typename OtherDerived> |
711 | EIGEN_DEVICE_FUNC |
712 | EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other) |
713 | { |
714 | internal::call_assignment(this->derived(), other.derived()); |
715 | return this->derived(); |
716 | } |
717 | |
718 | /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which |
719 | * is the case when creating a new matrix) so one can enforce lazy evaluation. |
720 | * |
721 | * \sa operator=(const MatrixBase<OtherDerived>&), _set() |
722 | */ |
723 | template<typename OtherDerived> |
724 | EIGEN_DEVICE_FUNC |
725 | EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other) |
726 | { |
727 | // I don't think we need this resize call since the lazyAssign will anyways resize |
728 | // and lazyAssign will be called by the assign selector. |
729 | //_resize_to_match(other); |
730 | // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because |
731 | // it wouldn't allow to copy a row-vector into a column-vector. |
732 | internal::call_assignment_no_alias(this->derived(), other.derived(), internal::assign_op<Scalar,typename OtherDerived::Scalar>()); |
733 | return this->derived(); |
734 | } |
735 | |
736 | template<typename T0, typename T1> |
737 | EIGEN_DEVICE_FUNC |
738 | EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0) |
739 | { |
740 | EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) && |
741 | bool(NumTraits<T1>::IsInteger), |
742 | FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) |
743 | resize(rows,cols); |
744 | } |
745 | |
746 | template<typename T0, typename T1> |
747 | EIGEN_DEVICE_FUNC |
748 | EIGEN_STRONG_INLINE void _init2(const T0& val0, const T1& val1, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0) |
749 | { |
750 | EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) |
751 | m_storage.data()[0] = Scalar(val0); |
752 | m_storage.data()[1] = Scalar(val1); |
753 | } |
754 | |
755 | template<typename T0, typename T1> |
756 | EIGEN_DEVICE_FUNC |
757 | EIGEN_STRONG_INLINE void _init2(const Index& val0, const Index& val1, |
758 | typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) |
759 | && (internal::is_same<T0,Index>::value) |
760 | && (internal::is_same<T1,Index>::value) |
761 | && Base::SizeAtCompileTime==2,T1>::type* = 0) |
762 | { |
763 | EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) |
764 | m_storage.data()[0] = Scalar(val0); |
765 | m_storage.data()[1] = Scalar(val1); |
766 | } |
767 | |
768 | // The argument is convertible to the Index type and we either have a non 1x1 Matrix, or a dynamic-sized Array, |
769 | // then the argument is meant to be the size of the object. |
770 | template<typename T> |
771 | EIGEN_DEVICE_FUNC |
772 | EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if< (Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value) |
773 | && ((!internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),T>::type* = 0) |
774 | { |
775 | // NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument. |
776 | const bool is_integer = NumTraits<T>::IsInteger; |
777 | EIGEN_UNUSED_VARIABLE(is_integer); |
778 | EIGEN_STATIC_ASSERT(is_integer, |
779 | FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) |
780 | resize(size); |
781 | } |
782 | |
783 | // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type can be implicitely converted) |
784 | template<typename T> |
785 | EIGEN_DEVICE_FUNC |
786 | EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0) |
787 | { |
788 | EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) |
789 | m_storage.data()[0] = val0; |
790 | } |
791 | |
792 | // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar type match the index type) |
793 | template<typename T> |
794 | EIGEN_DEVICE_FUNC |
795 | EIGEN_STRONG_INLINE void _init1(const Index& val0, |
796 | typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) |
797 | && (internal::is_same<Index,T>::value) |
798 | && Base::SizeAtCompileTime==1 |
799 | && internal::is_convertible<T, Scalar>::value,T*>::type* = 0) |
800 | { |
801 | EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) |
802 | m_storage.data()[0] = Scalar(val0); |
803 | } |
804 | |
805 | // Initialize a fixed size matrix from a pointer to raw data |
806 | template<typename T> |
807 | EIGEN_DEVICE_FUNC |
808 | EIGEN_STRONG_INLINE void _init1(const Scalar* data){ |
809 | this->_set_noalias(ConstMapType(data)); |
810 | } |
811 | |
812 | // Initialize an arbitrary matrix from a dense expression |
813 | template<typename T, typename OtherDerived> |
814 | EIGEN_DEVICE_FUNC |
815 | EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other){ |
816 | this->_set_noalias(other); |
817 | } |
818 | |
819 | // Initialize an arbitrary matrix from an object convertible to the Derived type. |
820 | template<typename T> |
821 | EIGEN_DEVICE_FUNC |
822 | EIGEN_STRONG_INLINE void _init1(const Derived& other){ |
823 | this->_set_noalias(other); |
824 | } |
825 | |
826 | // Initialize an arbitrary matrix from a generic Eigen expression |
827 | template<typename T, typename OtherDerived> |
828 | EIGEN_DEVICE_FUNC |
829 | EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other){ |
830 | this->derived() = other; |
831 | } |
832 | |
833 | template<typename T, typename OtherDerived> |
834 | EIGEN_DEVICE_FUNC |
835 | EIGEN_STRONG_INLINE void _init1(const ReturnByValue<OtherDerived>& other) |
836 | { |
837 | resize(other.rows(), other.cols()); |
838 | other.evalTo(this->derived()); |
839 | } |
840 | |
841 | template<typename T, typename OtherDerived, int ColsAtCompileTime> |
842 | EIGEN_DEVICE_FUNC |
843 | EIGEN_STRONG_INLINE void _init1(const RotationBase<OtherDerived,ColsAtCompileTime>& r) |
844 | { |
845 | this->derived() = r; |
846 | } |
847 | |
848 | // For fixed-size Array<Scalar,...> |
849 | template<typename T> |
850 | EIGEN_DEVICE_FUNC |
851 | EIGEN_STRONG_INLINE void _init1(const Scalar& val0, |
852 | typename internal::enable_if< Base::SizeAtCompileTime!=Dynamic |
853 | && Base::SizeAtCompileTime!=1 |
854 | && internal::is_convertible<T, Scalar>::value |
855 | && internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T>::type* = 0) |
856 | { |
857 | Base::setConstant(val0); |
858 | } |
859 | |
860 | // For fixed-size Array<Index,...> |
861 | template<typename T> |
862 | EIGEN_DEVICE_FUNC |
863 | EIGEN_STRONG_INLINE void _init1(const Index& val0, |
864 | typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) |
865 | && (internal::is_same<Index,T>::value) |
866 | && Base::SizeAtCompileTime!=Dynamic |
867 | && Base::SizeAtCompileTime!=1 |
868 | && internal::is_convertible<T, Scalar>::value |
869 | && internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T*>::type* = 0) |
870 | { |
871 | Base::setConstant(val0); |
872 | } |
873 | |
874 | template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> |
875 | friend struct internal::matrix_swap_impl; |
876 | |
877 | public: |
878 | |
879 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
880 | /** \internal |
881 | * \brief Override DenseBase::swap() since for dynamic-sized matrices |
882 | * of same type it is enough to swap the data pointers. |
883 | */ |
884 | template<typename OtherDerived> |
885 | EIGEN_DEVICE_FUNC |
886 | void swap(DenseBase<OtherDerived> & other) |
887 | { |
888 | enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic }; |
889 | internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.derived()); |
890 | } |
891 | |
892 | /** \internal |
893 | * \brief const version forwarded to DenseBase::swap |
894 | */ |
895 | template<typename OtherDerived> |
896 | EIGEN_DEVICE_FUNC |
897 | void swap(DenseBase<OtherDerived> const & other) |
898 | { Base::swap(other.derived()); } |
899 | |
900 | EIGEN_DEVICE_FUNC |
901 | static EIGEN_STRONG_INLINE void _check_template_params() |
902 | { |
903 | EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) |
904 | && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) |
905 | && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0)) |
906 | && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0)) |
907 | && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0)) |
908 | && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0)) |
909 | && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic) |
910 | && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic) |
911 | && (Options & (DontAlign|RowMajor)) == Options), |
912 | INVALID_MATRIX_TEMPLATE_PARAMETERS) |
913 | } |
914 | |
915 | enum { IsPlainObjectBase = 1 }; |
916 | #endif |
917 | }; |
918 | |
919 | namespace internal { |
920 | |
921 | template <typename Derived, typename OtherDerived, bool IsVector> |
922 | struct conservative_resize_like_impl |
923 | { |
924 | static void run(DenseBase<Derived>& _this, Index rows, Index cols) |
925 | { |
926 | if (_this.rows() == rows && _this.cols() == cols) return; |
927 | EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) |
928 | |
929 | if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows |
930 | (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns |
931 | { |
932 | internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime>::run(rows, cols); |
933 | _this.derived().m_storage.conservativeResize(rows*cols,rows,cols); |
934 | } |
935 | else |
936 | { |
937 | // The storage order does not allow us to use reallocation. |
938 | typename Derived::PlainObject tmp(rows,cols); |
939 | const Index common_rows = numext::mini(rows, _this.rows()); |
940 | const Index common_cols = numext::mini(cols, _this.cols()); |
941 | tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); |
942 | _this.derived().swap(tmp); |
943 | } |
944 | } |
945 | |
946 | static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) |
947 | { |
948 | if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; |
949 | |
950 | // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index), |
951 | // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the |
952 | // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or |
953 | // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like |
954 | // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good. |
955 | EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) |
956 | EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived) |
957 | |
958 | if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows |
959 | (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns |
960 | { |
961 | const Index new_rows = other.rows() - _this.rows(); |
962 | const Index new_cols = other.cols() - _this.cols(); |
963 | _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols()); |
964 | if (new_rows>0) |
965 | _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); |
966 | else if (new_cols>0) |
967 | _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); |
968 | } |
969 | else |
970 | { |
971 | // The storage order does not allow us to use reallocation. |
972 | typename Derived::PlainObject tmp(other); |
973 | const Index common_rows = numext::mini(tmp.rows(), _this.rows()); |
974 | const Index common_cols = numext::mini(tmp.cols(), _this.cols()); |
975 | tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); |
976 | _this.derived().swap(tmp); |
977 | } |
978 | } |
979 | }; |
980 | |
981 | // Here, the specialization for vectors inherits from the general matrix case |
982 | // to allow calling .conservativeResize(rows,cols) on vectors. |
983 | template <typename Derived, typename OtherDerived> |
984 | struct conservative_resize_like_impl<Derived,OtherDerived,true> |
985 | : conservative_resize_like_impl<Derived,OtherDerived,false> |
986 | { |
987 | using conservative_resize_like_impl<Derived,OtherDerived,false>::run; |
988 | |
989 | static void run(DenseBase<Derived>& _this, Index size) |
990 | { |
991 | const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size; |
992 | const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1; |
993 | _this.derived().m_storage.conservativeResize(size,new_rows,new_cols); |
994 | } |
995 | |
996 | static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) |
997 | { |
998 | if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; |
999 | |
1000 | const Index num_new_elements = other.size() - _this.size(); |
1001 | |
1002 | const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows(); |
1003 | const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1; |
1004 | _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols); |
1005 | |
1006 | if (num_new_elements > 0) |
1007 | _this.tail(num_new_elements) = other.tail(num_new_elements); |
1008 | } |
1009 | }; |
1010 | |
1011 | template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> |
1012 | struct matrix_swap_impl |
1013 | { |
1014 | EIGEN_DEVICE_FUNC |
1015 | static inline void run(MatrixTypeA& a, MatrixTypeB& b) |
1016 | { |
1017 | a.base().swap(b); |
1018 | } |
1019 | }; |
1020 | |
1021 | template<typename MatrixTypeA, typename MatrixTypeB> |
1022 | struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> |
1023 | { |
1024 | EIGEN_DEVICE_FUNC |
1025 | static inline void run(MatrixTypeA& a, MatrixTypeB& b) |
1026 | { |
1027 | static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage); |
1028 | } |
1029 | }; |
1030 | |
1031 | } // end namespace internal |
1032 | |
1033 | } // end namespace Eigen |
1034 | |
1035 | #endif // EIGEN_DENSESTORAGEBASE_H |
1036 | |