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 runcheck_rows_cols_for_overflow32 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 * \see class Map 581 */ 582 //@{ 583 static inline ConstMapType Map(const Scalar* data) 584 { return ConstMapType(data); } 585 static inline MapType Map(Scalar* data) 586 { return MapType(data); } 587 static inline ConstMapType Map(const Scalar* data, Index size) 588 { return ConstMapType(data, size); } 589 static inline MapType Map(Scalar* data, Index size) 590 { return MapType(data, size); } 591 static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) 592 { return ConstMapType(data, rows, cols); } 593 static inline MapType Map(Scalar* data, Index rows, Index cols) 594 { return MapType(data, rows, cols); } 595 596 static inline ConstAlignedMapType MapAligned(const Scalar* data) 597 { return ConstAlignedMapType(data); } 598 static inline AlignedMapType MapAligned(Scalar* data) 599 { return AlignedMapType(data); } 600 static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) 601 { return ConstAlignedMapType(data, size); } 602 static inline AlignedMapType MapAligned(Scalar* data, Index size) 603 { return AlignedMapType(data, size); } 604 static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) 605 { return ConstAlignedMapType(data, rows, cols); } 606 static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) 607 { return AlignedMapType(data, rows, cols); } 608 609 template<int Outer, int Inner> 610 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride) 611 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); } 612 template<int Outer, int Inner> 613 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride) 614 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); } 615 template<int Outer, int Inner> 616 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) 617 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); } 618 template<int Outer, int Inner> 619 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride) 620 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 621 template<int Outer, int Inner> 622 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 623 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 624 template<int Outer, int Inner> 625 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 626 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 627 628 template<int Outer, int Inner> 629 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride) 630 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } 631 template<int Outer, int Inner> 632 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride) 633 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } 634 template<int Outer, int Inner> 635 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) 636 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 637 template<int Outer, int Inner> 638 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride) 639 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 640 template<int Outer, int Inner> 641 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 642 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 643 template<int Outer, int Inner> 644 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 645 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 646 //@} 647 648 using Base::setConstant; 649 EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& val); 650 EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& val); 651 652 using Base::setZero; 653 EIGEN_DEVICE_FUNC Derived& setZero(Index size); 654 EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols); 655 656 using Base::setOnes; 657 EIGEN_DEVICE_FUNC Derived& setOnes(Index size); 658 EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols); 659 660 using Base::setRandom; 661 Derived& setRandom(Index size); 662 Derived& setRandom(Index rows, Index cols); 663 664 #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN 665 #include EIGEN_PLAINOBJECTBASE_PLUGIN 666 #endif 667 668 protected: 669 /** \internal Resizes *this in preparation for assigning \a other to it. 670 * Takes care of doing all the checking that's needed. 671 * 672 * Note that copying a row-vector into a vector (and conversely) is allowed. 673 * The resizing, if any, is then done in the appropriate way so that row-vectors 674 * remain row-vectors and vectors remain vectors. 675 */ 676 template<typename OtherDerived> 677 EIGEN_DEVICE_FUNC 678 EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) 679 { 680 #ifdef EIGEN_NO_AUTOMATIC_RESIZING 681 eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size()) 682 : (rows() == other.rows() && cols() == other.cols()))) 683 && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined"); 684 EIGEN_ONLY_USED_FOR_DEBUG(other); 685 #else 686 resizeLike(other); 687 #endif 688 } 689 690 /** 691 * \brief Copies the value of the expression \a other into \c *this with automatic resizing. 692 * 693 * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), 694 * it will be initialized. 695 * 696 * Note that copying a row-vector into a vector (and conversely) is allowed. 697 * The resizing, if any, is then done in the appropriate way so that row-vectors 698 * remain row-vectors and vectors remain vectors. 699 * 700 * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias() 701 * 702 * \internal 703 */ 704 // aliasing is dealt once in internall::call_assignment 705 // so at this stage we have to assume aliasing... and resising has to be done later. 706 template<typename OtherDerived> 707 EIGEN_DEVICE_FUNC 708 EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other) 709 { 710 internal::call_assignment(this->derived(), other.derived()); 711 return this->derived(); 712 } 713 714 /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which 715 * is the case when creating a new matrix) so one can enforce lazy evaluation. 716 * 717 * \sa operator=(const MatrixBase<OtherDerived>&), _set() 718 */ 719 template<typename OtherDerived> 720 EIGEN_DEVICE_FUNC 721 EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other) 722 { 723 // I don't think we need this resize call since the lazyAssign will anyways resize 724 // and lazyAssign will be called by the assign selector. 725 //_resize_to_match(other); 726 // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because 727 // it wouldn't allow to copy a row-vector into a column-vector. 728 internal::call_assignment_no_alias(this->derived(), other.derived(), internal::assign_op<Scalar,typename OtherDerived::Scalar>()); 729 return this->derived(); 730 } 731 732 template<typename T0, typename T1> 733 EIGEN_DEVICE_FUNC 734 EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0) 735 { 736 EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) && 737 bool(NumTraits<T1>::IsInteger), 738 FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) 739 resize(rows,cols); 740 } 741 742 template<typename T0, typename T1> 743 EIGEN_DEVICE_FUNC 744 EIGEN_STRONG_INLINE void _init2(const T0& val0, const T1& val1, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0) 745 { 746 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) 747 m_storage.data()[0] = Scalar(val0); 748 m_storage.data()[1] = Scalar(val1); 749 } 750 751 template<typename T0, typename T1> 752 EIGEN_DEVICE_FUNC 753 EIGEN_STRONG_INLINE void _init2(const Index& val0, const Index& val1, 754 typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) 755 && (internal::is_same<T0,Index>::value) 756 && (internal::is_same<T1,Index>::value) 757 && Base::SizeAtCompileTime==2,T1>::type* = 0) 758 { 759 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) 760 m_storage.data()[0] = Scalar(val0); 761 m_storage.data()[1] = Scalar(val1); 762 } 763 764 // The argument is convertible to the Index type and we either have a non 1x1 Matrix, or a dynamic-sized Array, 765 // then the argument is meant to be the size of the object. 766 template<typename T> 767 EIGEN_DEVICE_FUNC 768 EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if< (Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value) 769 && ((!internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value || Base::SizeAtCompileTime==Dynamic)),T>::type* = 0) 770 { 771 // NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument. 772 const bool is_integer = NumTraits<T>::IsInteger; 773 EIGEN_UNUSED_VARIABLE(is_integer); 774 EIGEN_STATIC_ASSERT(is_integer, 775 FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) 776 resize(size); 777 } 778 779 // 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) 780 template<typename T> 781 EIGEN_DEVICE_FUNC 782 EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0) 783 { 784 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) 785 m_storage.data()[0] = val0; 786 } 787 788 // 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) 789 template<typename T> 790 EIGEN_DEVICE_FUNC 791 EIGEN_STRONG_INLINE void _init1(const Index& val0, 792 typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) 793 && (internal::is_same<Index,T>::value) 794 && Base::SizeAtCompileTime==1 795 && internal::is_convertible<T, Scalar>::value,T*>::type* = 0) 796 { 797 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1) 798 m_storage.data()[0] = Scalar(val0); 799 } 800 801 // Initialize a fixed size matrix from a pointer to raw data 802 template<typename T> 803 EIGEN_DEVICE_FUNC 804 EIGEN_STRONG_INLINE void _init1(const Scalar* data){ 805 this->_set_noalias(ConstMapType(data)); 806 } 807 808 // Initialize an arbitrary matrix from a dense expression 809 template<typename T, typename OtherDerived> 810 EIGEN_DEVICE_FUNC 811 EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other){ 812 this->_set_noalias(other); 813 } 814 815 // Initialize an arbitrary matrix from an object convertible to the Derived type. 816 template<typename T> 817 EIGEN_DEVICE_FUNC 818 EIGEN_STRONG_INLINE void _init1(const Derived& other){ 819 this->_set_noalias(other); 820 } 821 822 // Initialize an arbitrary matrix from a generic Eigen expression 823 template<typename T, typename OtherDerived> 824 EIGEN_DEVICE_FUNC 825 EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other){ 826 this->derived() = other; 827 } 828 829 template<typename T, typename OtherDerived> 830 EIGEN_DEVICE_FUNC 831 EIGEN_STRONG_INLINE void _init1(const ReturnByValue<OtherDerived>& other) 832 { 833 resize(other.rows(), other.cols()); 834 other.evalTo(this->derived()); 835 } 836 837 template<typename T, typename OtherDerived, int ColsAtCompileTime> 838 EIGEN_DEVICE_FUNC 839 EIGEN_STRONG_INLINE void _init1(const RotationBase<OtherDerived,ColsAtCompileTime>& r) 840 { 841 this->derived() = r; 842 } 843 844 // For fixed-size Array<Scalar,...> 845 template<typename T> 846 EIGEN_DEVICE_FUNC 847 EIGEN_STRONG_INLINE void _init1(const Scalar& val0, 848 typename internal::enable_if< Base::SizeAtCompileTime!=Dynamic 849 && Base::SizeAtCompileTime!=1 850 && internal::is_convertible<T, Scalar>::value 851 && internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T>::type* = 0) 852 { 853 Base::setConstant(val0); 854 } 855 856 // For fixed-size Array<Index,...> 857 template<typename T> 858 EIGEN_DEVICE_FUNC 859 EIGEN_STRONG_INLINE void _init1(const Index& val0, 860 typename internal::enable_if< (!internal::is_same<Index,Scalar>::value) 861 && (internal::is_same<Index,T>::value) 862 && Base::SizeAtCompileTime!=Dynamic 863 && Base::SizeAtCompileTime!=1 864 && internal::is_convertible<T, Scalar>::value 865 && internal::is_same<typename internal::traits<Derived>::XprKind,ArrayXpr>::value,T*>::type* = 0) 866 { 867 Base::setConstant(val0); 868 } 869 870 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> 871 friend struct internal::matrix_swap_impl; 872 873 public: 874 875 #ifndef EIGEN_PARSED_BY_DOXYGEN 876 /** \internal 877 * \brief Override DenseBase::swap() since for dynamic-sized matrices 878 * of same type it is enough to swap the data pointers. 879 */ 880 template<typename OtherDerived> 881 EIGEN_DEVICE_FUNC 882 void swap(DenseBase<OtherDerived> & other) 883 { 884 enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic }; 885 internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.derived()); 886 } 887 888 /** \internal 889 * \brief const version forwarded to DenseBase::swap 890 */ 891 template<typename OtherDerived> 892 EIGEN_DEVICE_FUNC 893 void swap(DenseBase<OtherDerived> const & other) 894 { Base::swap(other.derived()); } 895 896 EIGEN_DEVICE_FUNC 897 static EIGEN_STRONG_INLINE void _check_template_params() 898 { 899 EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) 900 && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) 901 && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0)) 902 && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0)) 903 && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0)) 904 && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0)) 905 && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic) 906 && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic) 907 && (Options & (DontAlign|RowMajor)) == Options), 908 INVALID_MATRIX_TEMPLATE_PARAMETERS) 909 } 910 911 enum { IsPlainObjectBase = 1 }; 912 #endif 913 }; 914 915 namespace internal { 916 917 template <typename Derived, typename OtherDerived, bool IsVector> 918 struct conservative_resize_like_impl 919 { 920 static void run(DenseBase<Derived>& _this, Index rows, Index cols) 921 { 922 if (_this.rows() == rows && _this.cols() == cols) return; 923 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) 924 925 if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows 926 (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns 927 { 928 internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime>::run(rows, cols); 929 _this.derived().m_storage.conservativeResize(rows*cols,rows,cols); 930 } 931 else 932 { 933 // The storage order does not allow us to use reallocation. 934 typename Derived::PlainObject tmp(rows,cols); 935 const Index common_rows = numext::mini(rows, _this.rows()); 936 const Index common_cols = numext::mini(cols, _this.cols()); 937 tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); 938 _this.derived().swap(tmp); 939 } 940 } 941 942 static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) 943 { 944 if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; 945 946 // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index), 947 // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the 948 // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or 949 // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like 950 // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good. 951 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) 952 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived) 953 954 if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows 955 (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns 956 { 957 const Index new_rows = other.rows() - _this.rows(); 958 const Index new_cols = other.cols() - _this.cols(); 959 _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols()); 960 if (new_rows>0) 961 _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); 962 else if (new_cols>0) 963 _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); 964 } 965 else 966 { 967 // The storage order does not allow us to use reallocation. 968 typename Derived::PlainObject tmp(other); 969 const Index common_rows = numext::mini(tmp.rows(), _this.rows()); 970 const Index common_cols = numext::mini(tmp.cols(), _this.cols()); 971 tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); 972 _this.derived().swap(tmp); 973 } 974 } 975 }; 976 977 // Here, the specialization for vectors inherits from the general matrix case 978 // to allow calling .conservativeResize(rows,cols) on vectors. 979 template <typename Derived, typename OtherDerived> 980 struct conservative_resize_like_impl<Derived,OtherDerived,true> 981 : conservative_resize_like_impl<Derived,OtherDerived,false> 982 { 983 using conservative_resize_like_impl<Derived,OtherDerived,false>::run; 984 985 static void run(DenseBase<Derived>& _this, Index size) 986 { 987 const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size; 988 const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1; 989 _this.derived().m_storage.conservativeResize(size,new_rows,new_cols); 990 } 991 992 static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) 993 { 994 if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; 995 996 const Index num_new_elements = other.size() - _this.size(); 997 998 const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows(); 999 const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1; 1000 _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols); 1001 1002 if (num_new_elements > 0) 1003 _this.tail(num_new_elements) = other.tail(num_new_elements); 1004 } 1005 }; 1006 1007 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> 1008 struct matrix_swap_impl 1009 { 1010 EIGEN_DEVICE_FUNC 1011 static inline void run(MatrixTypeA& a, MatrixTypeB& b) 1012 { 1013 a.base().swap(b); 1014 } 1015 }; 1016 1017 template<typename MatrixTypeA, typename MatrixTypeB> 1018 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> 1019 { 1020 EIGEN_DEVICE_FUNC 1021 static inline void run(MatrixTypeA& a, MatrixTypeB& b) 1022 { 1023 static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage); 1024 } 1025 }; 1026 1027 } // end namespace internal 1028 1029 } // end namespace Eigen 1030 1031 #endif // EIGEN_DENSESTORAGEBASE_H 1032