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