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
25namespace Eigen {
26
27namespace internal {
28
29template<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
37template<> 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
52template <typename Derived,
53 typename OtherDerived = Derived,
54 bool IsVector = bool(Derived::IsVectorAtCompileTime) && bool(OtherDerived::IsVectorAtCompileTime)>
55struct conservative_resize_like_impl;
56
57template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
58
59} // end namespace internal
60
61#ifdef EIGEN_PARSED_BY_DOXYGEN
62namespace 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. */
71template<typename Derived> struct dense_xpr_base_dispatcher;
72/** This class is just a workaround for Doxygen and it does not not actually exist. */
73template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
74struct 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. */
77template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
78struct 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 */
94template<typename Derived>
95class PlainObjectBase : public doxygen::dense_xpr_base_dispatcher<Derived>
96#else
97template<typename Derived>
98class 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
919namespace internal {
920
921template <typename Derived, typename OtherDerived, bool IsVector>
922struct 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.
983template <typename Derived, typename OtherDerived>
984struct 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
1011template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
1012struct 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
1021template<typename MatrixTypeA, typename MatrixTypeB>
1022struct 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