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 (at) inria.fr> 5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1 (at) 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 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO 15 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0); 16 #else 17 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 18 #endif 19 20 namespace Eigen { 21 22 namespace internal { 23 24 template<typename Index> 25 EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols) 26 { 27 // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 28 // we assume Index is signed 29 Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed 30 bool error = (rows < 0 || cols < 0) ? true 31 : (rows == 0 || cols == 0) ? false 32 : (rows > max_index / cols); 33 if (error) 34 throw_std_bad_alloc(); 35 } 36 37 template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl; 38 39 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl; 40 41 } // end namespace internal 42 43 /** \class PlainObjectBase 44 * \brief %Dense storage base class for matrices and arrays. 45 * 46 * This class can be extended with the help of the plugin mechanism described on the page 47 * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN. 48 * 49 * \sa \ref TopicClassHierarchy 50 */ 51 #ifdef EIGEN_PARSED_BY_DOXYGEN 52 namespace internal { 53 54 // this is a warkaround to doxygen not being able to understand the inheritence logic 55 // when it is hidden by the dense_xpr_base helper struct. 56 template<typename Derived> struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase<Derived> {}; 57 /** This class is just a workaround for Doxygen and it does not not actually exist. */ 58 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 59 struct dense_xpr_base_dispatcher_for_doxygen<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > 60 : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {}; 61 /** This class is just a workaround for Doxygen and it does not not actually exist. */ 62 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> 63 struct dense_xpr_base_dispatcher_for_doxygen<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > 64 : public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {}; 65 66 } // namespace internal 67 68 template<typename Derived> 69 class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen<Derived> 70 #else 71 template<typename Derived> 72 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type 73 #endif 74 { 75 public: 76 enum { Options = internal::traits<Derived>::Options }; 77 typedef typename internal::dense_xpr_base<Derived>::type Base; 78 79 typedef typename internal::traits<Derived>::StorageKind StorageKind; 80 typedef typename internal::traits<Derived>::Index Index; 81 typedef typename internal::traits<Derived>::Scalar Scalar; 82 typedef typename internal::packet_traits<Scalar>::type PacketScalar; 83 typedef typename NumTraits<Scalar>::Real RealScalar; 84 typedef Derived DenseType; 85 86 using Base::RowsAtCompileTime; 87 using Base::ColsAtCompileTime; 88 using Base::SizeAtCompileTime; 89 using Base::MaxRowsAtCompileTime; 90 using Base::MaxColsAtCompileTime; 91 using Base::MaxSizeAtCompileTime; 92 using Base::IsVectorAtCompileTime; 93 using Base::Flags; 94 95 template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map; 96 friend class Eigen::Map<Derived, Unaligned>; 97 typedef Eigen::Map<Derived, Unaligned> MapType; 98 friend class Eigen::Map<const Derived, Unaligned>; 99 typedef const Eigen::Map<const Derived, Unaligned> ConstMapType; 100 friend class Eigen::Map<Derived, Aligned>; 101 typedef Eigen::Map<Derived, Aligned> AlignedMapType; 102 friend class Eigen::Map<const Derived, Aligned>; 103 typedef const Eigen::Map<const Derived, Aligned> ConstAlignedMapType; 104 template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; }; 105 template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; }; 106 template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; }; 107 template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; }; 108 109 protected: 110 DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage; 111 112 public: 113 enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 }; 114 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) 115 116 Base& base() { return *static_cast<Base*>(this); } 117 const Base& base() const { return *static_cast<const Base*>(this); } 118 119 EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); } 120 EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); } 121 122 EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const 123 { 124 if(Flags & RowMajorBit) 125 return m_storage.data()[col + row * m_storage.cols()]; 126 else // column-major 127 return m_storage.data()[row + col * m_storage.rows()]; 128 } 129 130 EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const 131 { 132 return m_storage.data()[index]; 133 } 134 135 EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) 136 { 137 if(Flags & RowMajorBit) 138 return m_storage.data()[col + row * m_storage.cols()]; 139 else // column-major 140 return m_storage.data()[row + col * m_storage.rows()]; 141 } 142 143 EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) 144 { 145 return m_storage.data()[index]; 146 } 147 148 EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const 149 { 150 if(Flags & RowMajorBit) 151 return m_storage.data()[col + row * m_storage.cols()]; 152 else // column-major 153 return m_storage.data()[row + col * m_storage.rows()]; 154 } 155 156 EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const 157 { 158 return m_storage.data()[index]; 159 } 160 161 /** \internal */ 162 template<int LoadMode> 163 EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const 164 { 165 return internal::ploadt<PacketScalar, LoadMode> 166 (m_storage.data() + (Flags & RowMajorBit 167 ? col + row * m_storage.cols() 168 : row + col * m_storage.rows())); 169 } 170 171 /** \internal */ 172 template<int LoadMode> 173 EIGEN_STRONG_INLINE PacketScalar packet(Index index) const 174 { 175 return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index); 176 } 177 178 /** \internal */ 179 template<int StoreMode> 180 EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x) 181 { 182 internal::pstoret<Scalar, PacketScalar, StoreMode> 183 (m_storage.data() + (Flags & RowMajorBit 184 ? col + row * m_storage.cols() 185 : row + col * m_storage.rows()), x); 186 } 187 188 /** \internal */ 189 template<int StoreMode> 190 EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x) 191 { 192 internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x); 193 } 194 195 /** \returns a const pointer to the data array of this matrix */ 196 EIGEN_STRONG_INLINE const Scalar *data() const 197 { return m_storage.data(); } 198 199 /** \returns a pointer to the data array of this matrix */ 200 EIGEN_STRONG_INLINE Scalar *data() 201 { return m_storage.data(); } 202 203 /** Resizes \c *this to a \a rows x \a cols matrix. 204 * 205 * This method is intended for dynamic-size matrices, although it is legal to call it on any 206 * matrix as long as fixed dimensions are left unchanged. If you only want to change the number 207 * of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t). 208 * 209 * If the current number of coefficients of \c *this exactly matches the 210 * product \a rows * \a cols, then no memory allocation is performed and 211 * the current values are left unchanged. In all other cases, including 212 * shrinking, the data is reallocated and all previous values are lost. 213 * 214 * Example: \include Matrix_resize_int_int.cpp 215 * Output: \verbinclude Matrix_resize_int_int.out 216 * 217 * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t) 218 */ 219 EIGEN_STRONG_INLINE void resize(Index rows, Index cols) 220 { 221 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO 222 internal::check_rows_cols_for_overflow(rows, cols); 223 Index size = rows*cols; 224 bool size_changed = size != this->size(); 225 m_storage.resize(size, rows, cols); 226 if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 227 #else 228 internal::check_rows_cols_for_overflow(rows, cols); 229 m_storage.resize(rows*cols, rows, cols); 230 #endif 231 } 232 233 /** Resizes \c *this to a vector of length \a size 234 * 235 * \only_for_vectors. This method does not work for 236 * partially dynamic matrices when the static dimension is anything other 237 * than 1. For example it will not work with Matrix<double, 2, Dynamic>. 238 * 239 * Example: \include Matrix_resize_int.cpp 240 * Output: \verbinclude Matrix_resize_int.out 241 * 242 * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t) 243 */ 244 inline void resize(Index size) 245 { 246 EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase) 247 eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size); 248 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO 249 bool size_changed = size != this->size(); 250 #endif 251 if(RowsAtCompileTime == 1) 252 m_storage.resize(size, 1, size); 253 else 254 m_storage.resize(size, size, 1); 255 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO 256 if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 257 #endif 258 } 259 260 /** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the special value \c NoChange 261 * as in the example below. 262 * 263 * Example: \include Matrix_resize_NoChange_int.cpp 264 * Output: \verbinclude Matrix_resize_NoChange_int.out 265 * 266 * \sa resize(Index,Index) 267 */ 268 inline void resize(NoChange_t, Index cols) 269 { 270 resize(rows(), cols); 271 } 272 273 /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange 274 * as in the example below. 275 * 276 * Example: \include Matrix_resize_int_NoChange.cpp 277 * Output: \verbinclude Matrix_resize_int_NoChange.out 278 * 279 * \sa resize(Index,Index) 280 */ 281 inline void resize(Index rows, NoChange_t) 282 { 283 resize(rows, cols()); 284 } 285 286 /** Resizes \c *this to have the same dimensions as \a other. 287 * Takes care of doing all the checking that's needed. 288 * 289 * Note that copying a row-vector into a vector (and conversely) is allowed. 290 * The resizing, if any, is then done in the appropriate way so that row-vectors 291 * remain row-vectors and vectors remain vectors. 292 */ 293 template<typename OtherDerived> 294 EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other) 295 { 296 const OtherDerived& other = _other.derived(); 297 internal::check_rows_cols_for_overflow(other.rows(), other.cols()); 298 const Index othersize = other.rows()*other.cols(); 299 if(RowsAtCompileTime == 1) 300 { 301 eigen_assert(other.rows() == 1 || other.cols() == 1); 302 resize(1, othersize); 303 } 304 else if(ColsAtCompileTime == 1) 305 { 306 eigen_assert(other.rows() == 1 || other.cols() == 1); 307 resize(othersize, 1); 308 } 309 else resize(other.rows(), other.cols()); 310 } 311 312 /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. 313 * 314 * The method is intended for matrices of dynamic size. If you only want to change the number 315 * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or 316 * conservativeResize(Index, NoChange_t). 317 * 318 * Matrices are resized relative to the top-left element. In case values need to be 319 * appended to the matrix they will be uninitialized. 320 */ 321 EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols) 322 { 323 internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols); 324 } 325 326 /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. 327 * 328 * As opposed to conservativeResize(Index rows, Index cols), this version leaves 329 * the number of columns unchanged. 330 * 331 * In case the matrix is growing, new rows will be uninitialized. 332 */ 333 EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t) 334 { 335 // Note: see the comment in conservativeResize(Index,Index) 336 conservativeResize(rows, cols()); 337 } 338 339 /** Resizes the matrix to \a rows x \a cols while leaving old values untouched. 340 * 341 * As opposed to conservativeResize(Index rows, Index cols), this version leaves 342 * the number of rows unchanged. 343 * 344 * In case the matrix is growing, new columns will be uninitialized. 345 */ 346 EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols) 347 { 348 // Note: see the comment in conservativeResize(Index,Index) 349 conservativeResize(rows(), cols); 350 } 351 352 /** Resizes the vector to \a size while retaining old values. 353 * 354 * \only_for_vectors. This method does not work for 355 * partially dynamic matrices when the static dimension is anything other 356 * than 1. For example it will not work with Matrix<double, 2, Dynamic>. 357 * 358 * When values are appended, they will be uninitialized. 359 */ 360 EIGEN_STRONG_INLINE void conservativeResize(Index size) 361 { 362 internal::conservative_resize_like_impl<Derived>::run(*this, size); 363 } 364 365 /** Resizes the matrix to \a rows x \a cols of \c other, while leaving old values untouched. 366 * 367 * The method is intended for matrices of dynamic size. If you only want to change the number 368 * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or 369 * conservativeResize(Index, NoChange_t). 370 * 371 * Matrices are resized relative to the top-left element. In case values need to be 372 * appended to the matrix they will copied from \c other. 373 */ 374 template<typename OtherDerived> 375 EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other) 376 { 377 internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other); 378 } 379 380 /** This is a special case of the templated operator=. Its purpose is to 381 * prevent a default operator= from hiding the templated operator=. 382 */ 383 EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other) 384 { 385 return _set(other); 386 } 387 388 /** \sa MatrixBase::lazyAssign() */ 389 template<typename OtherDerived> 390 EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other) 391 { 392 _resize_to_match(other); 393 return Base::lazyAssign(other.derived()); 394 } 395 396 template<typename OtherDerived> 397 EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func) 398 { 399 resize(func.rows(), func.cols()); 400 return Base::operator=(func); 401 } 402 403 EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage() 404 { 405 // _check_template_params(); 406 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 407 } 408 409 #ifndef EIGEN_PARSED_BY_DOXYGEN 410 // FIXME is it still needed ? 411 /** \internal */ 412 PlainObjectBase(internal::constructor_without_unaligned_array_assert) 413 : m_storage(internal::constructor_without_unaligned_array_assert()) 414 { 415 // _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 416 } 417 #endif 418 419 EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols) 420 : m_storage(size, rows, cols) 421 { 422 // _check_template_params(); 423 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 424 } 425 426 /** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&) 427 */ 428 template<typename OtherDerived> 429 EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other) 430 { 431 _resize_to_match(other); 432 Base::operator=(other.derived()); 433 return this->derived(); 434 } 435 436 /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */ 437 template<typename OtherDerived> 438 EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other) 439 : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols()) 440 { 441 _check_template_params(); 442 internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols()); 443 Base::operator=(other.derived()); 444 } 445 446 /** \name Map 447 * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects, 448 * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned 449 * \a data pointers. 450 * 451 * \see class Map 452 */ 453 //@{ 454 static inline ConstMapType Map(const Scalar* data) 455 { return ConstMapType(data); } 456 static inline MapType Map(Scalar* data) 457 { return MapType(data); } 458 static inline ConstMapType Map(const Scalar* data, Index size) 459 { return ConstMapType(data, size); } 460 static inline MapType Map(Scalar* data, Index size) 461 { return MapType(data, size); } 462 static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) 463 { return ConstMapType(data, rows, cols); } 464 static inline MapType Map(Scalar* data, Index rows, Index cols) 465 { return MapType(data, rows, cols); } 466 467 static inline ConstAlignedMapType MapAligned(const Scalar* data) 468 { return ConstAlignedMapType(data); } 469 static inline AlignedMapType MapAligned(Scalar* data) 470 { return AlignedMapType(data); } 471 static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) 472 { return ConstAlignedMapType(data, size); } 473 static inline AlignedMapType MapAligned(Scalar* data, Index size) 474 { return AlignedMapType(data, size); } 475 static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) 476 { return ConstAlignedMapType(data, rows, cols); } 477 static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) 478 { return AlignedMapType(data, rows, cols); } 479 480 template<int Outer, int Inner> 481 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride) 482 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); } 483 template<int Outer, int Inner> 484 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride) 485 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); } 486 template<int Outer, int Inner> 487 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) 488 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); } 489 template<int Outer, int Inner> 490 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride) 491 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 492 template<int Outer, int Inner> 493 static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 494 { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 495 template<int Outer, int Inner> 496 static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 497 { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 498 499 template<int Outer, int Inner> 500 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride) 501 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } 502 template<int Outer, int Inner> 503 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride) 504 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } 505 template<int Outer, int Inner> 506 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) 507 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 508 template<int Outer, int Inner> 509 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride) 510 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } 511 template<int Outer, int Inner> 512 static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 513 { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 514 template<int Outer, int Inner> 515 static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) 516 { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } 517 //@} 518 519 using Base::setConstant; 520 Derived& setConstant(Index size, const Scalar& value); 521 Derived& setConstant(Index rows, Index cols, const Scalar& value); 522 523 using Base::setZero; 524 Derived& setZero(Index size); 525 Derived& setZero(Index rows, Index cols); 526 527 using Base::setOnes; 528 Derived& setOnes(Index size); 529 Derived& setOnes(Index rows, Index cols); 530 531 using Base::setRandom; 532 Derived& setRandom(Index size); 533 Derived& setRandom(Index rows, Index cols); 534 535 #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN 536 #include EIGEN_PLAINOBJECTBASE_PLUGIN 537 #endif 538 539 protected: 540 /** \internal Resizes *this in preparation for assigning \a other to it. 541 * Takes care of doing all the checking that's needed. 542 * 543 * Note that copying a row-vector into a vector (and conversely) is allowed. 544 * The resizing, if any, is then done in the appropriate way so that row-vectors 545 * remain row-vectors and vectors remain vectors. 546 */ 547 template<typename OtherDerived> 548 EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) 549 { 550 #ifdef EIGEN_NO_AUTOMATIC_RESIZING 551 eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size()) 552 : (rows() == other.rows() && cols() == other.cols()))) 553 && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined"); 554 #else 555 resizeLike(other); 556 #endif 557 } 558 559 /** 560 * \brief Copies the value of the expression \a other into \c *this with automatic resizing. 561 * 562 * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), 563 * it will be initialized. 564 * 565 * Note that copying a row-vector into a vector (and conversely) is allowed. 566 * The resizing, if any, is then done in the appropriate way so that row-vectors 567 * remain row-vectors and vectors remain vectors. 568 * 569 * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias() 570 * 571 * \internal 572 */ 573 template<typename OtherDerived> 574 EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other) 575 { 576 _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type()); 577 return this->derived(); 578 } 579 580 template<typename OtherDerived> 581 EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); } 582 583 template<typename OtherDerived> 584 EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); } 585 586 /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which 587 * is the case when creating a new matrix) so one can enforce lazy evaluation. 588 * 589 * \sa operator=(const MatrixBase<OtherDerived>&), _set() 590 */ 591 template<typename OtherDerived> 592 EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other) 593 { 594 // I don't think we need this resize call since the lazyAssign will anyways resize 595 // and lazyAssign will be called by the assign selector. 596 //_resize_to_match(other); 597 // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because 598 // it wouldn't allow to copy a row-vector into a column-vector. 599 return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived()); 600 } 601 602 template<typename T0, typename T1> 603 EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0) 604 { 605 EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) && 606 bool(NumTraits<T1>::IsInteger), 607 FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) 608 eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) 609 && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); 610 internal::check_rows_cols_for_overflow(rows, cols); 611 m_storage.resize(rows*cols,rows,cols); 612 EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED 613 } 614 template<typename T0, typename T1> 615 EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0) 616 { 617 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) 618 m_storage.data()[0] = x; 619 m_storage.data()[1] = y; 620 } 621 622 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> 623 friend struct internal::matrix_swap_impl; 624 625 /** \internal generic implementation of swap for dense storage since for dynamic-sized matrices of same type it is enough to swap the 626 * data pointers. 627 */ 628 template<typename OtherDerived> 629 void _swap(DenseBase<OtherDerived> const & other) 630 { 631 enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic }; 632 internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived()); 633 } 634 635 public: 636 #ifndef EIGEN_PARSED_BY_DOXYGEN 637 static EIGEN_STRONG_INLINE void _check_template_params() 638 { 639 EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) 640 && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) 641 && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0)) 642 && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0)) 643 && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0)) 644 && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0)) 645 && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic) 646 && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic) 647 && (Options & (DontAlign|RowMajor)) == Options), 648 INVALID_MATRIX_TEMPLATE_PARAMETERS) 649 } 650 #endif 651 652 private: 653 enum { ThisConstantIsPrivateInPlainObjectBase }; 654 }; 655 656 template <typename Derived, typename OtherDerived, bool IsVector> 657 struct internal::conservative_resize_like_impl 658 { 659 typedef typename Derived::Index Index; 660 static void run(DenseBase<Derived>& _this, Index rows, Index cols) 661 { 662 if (_this.rows() == rows && _this.cols() == cols) return; 663 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) 664 665 if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows 666 (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns 667 { 668 internal::check_rows_cols_for_overflow(rows, cols); 669 _this.derived().m_storage.conservativeResize(rows*cols,rows,cols); 670 } 671 else 672 { 673 // The storage order does not allow us to use reallocation. 674 typename Derived::PlainObject tmp(rows,cols); 675 const Index common_rows = (std::min)(rows, _this.rows()); 676 const Index common_cols = (std::min)(cols, _this.cols()); 677 tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); 678 _this.derived().swap(tmp); 679 } 680 } 681 682 static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) 683 { 684 if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; 685 686 // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index), 687 // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the 688 // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or 689 // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like 690 // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good. 691 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) 692 EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived) 693 694 if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows 695 (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns 696 { 697 const Index new_rows = other.rows() - _this.rows(); 698 const Index new_cols = other.cols() - _this.cols(); 699 _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols()); 700 if (new_rows>0) 701 _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); 702 else if (new_cols>0) 703 _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); 704 } 705 else 706 { 707 // The storage order does not allow us to use reallocation. 708 typename Derived::PlainObject tmp(other); 709 const Index common_rows = (std::min)(tmp.rows(), _this.rows()); 710 const Index common_cols = (std::min)(tmp.cols(), _this.cols()); 711 tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); 712 _this.derived().swap(tmp); 713 } 714 } 715 }; 716 717 namespace internal { 718 719 template <typename Derived, typename OtherDerived> 720 struct conservative_resize_like_impl<Derived,OtherDerived,true> 721 { 722 typedef typename Derived::Index Index; 723 static void run(DenseBase<Derived>& _this, Index size) 724 { 725 const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size; 726 const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1; 727 _this.derived().m_storage.conservativeResize(size,new_rows,new_cols); 728 } 729 730 static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) 731 { 732 if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; 733 734 const Index num_new_elements = other.size() - _this.size(); 735 736 const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows(); 737 const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1; 738 _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols); 739 740 if (num_new_elements > 0) 741 _this.tail(num_new_elements) = other.tail(num_new_elements); 742 } 743 }; 744 745 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> 746 struct matrix_swap_impl 747 { 748 static inline void run(MatrixTypeA& a, MatrixTypeB& b) 749 { 750 a.base().swap(b); 751 } 752 }; 753 754 template<typename MatrixTypeA, typename MatrixTypeB> 755 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> 756 { 757 static inline void run(MatrixTypeA& a, MatrixTypeB& b) 758 { 759 static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage); 760 } 761 }; 762 763 } // end namespace internal 764 765 } // end namespace Eigen 766 767 #endif // EIGEN_DENSESTORAGEBASE_H 768