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