PlainObjectBase.h 44 KB

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