Home | History | Annotate | Download | only in Core
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 // Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1 (at) gmail.com>
      6 // Copyright (C) 2010-2013 Hauke Heibel <hauke.heibel (at) gmail.com>
      7 //
      8 // This Source Code Form is subject to the terms of the Mozilla
      9 // Public License v. 2.0. If a copy of the MPL was not distributed
     10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     11 
     12 #ifndef EIGEN_MATRIXSTORAGE_H
     13 #define EIGEN_MATRIXSTORAGE_H
     14 
     15 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
     16   #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) X; EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
     17 #else
     18   #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X)
     19 #endif
     20 
     21 namespace Eigen {
     22 
     23 namespace internal {
     24 
     25 struct constructor_without_unaligned_array_assert {};
     26 
     27 template<typename T, int Size>
     28 EIGEN_DEVICE_FUNC
     29 void check_static_allocation_size()
     30 {
     31   // if EIGEN_STACK_ALLOCATION_LIMIT is defined to 0, then no limit
     32   #if EIGEN_STACK_ALLOCATION_LIMIT
     33   EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
     34   #endif
     35 }
     36 
     37 /** \internal
     38   * Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
     39   * to 16 bytes boundary if the total size is a multiple of 16 bytes.
     40   */
     41 template <typename T, int Size, int MatrixOrArrayOptions,
     42           int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
     43                         : compute_default_alignment<T,Size>::value >
     44 struct plain_array
     45 {
     46   T array[Size];
     47 
     48   EIGEN_DEVICE_FUNC
     49   plain_array()
     50   {
     51     check_static_allocation_size<T,Size>();
     52   }
     53 
     54   EIGEN_DEVICE_FUNC
     55   plain_array(constructor_without_unaligned_array_assert)
     56   {
     57     check_static_allocation_size<T,Size>();
     58   }
     59 };
     60 
     61 #if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
     62   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
     63 #elif EIGEN_GNUC_AT_LEAST(4,7)
     64   // GCC 4.7 is too aggressive in its optimizations and remove the alignement test based on the fact the array is declared to be aligned.
     65   // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
     66   // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
     67   template<typename PtrType>
     68   EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
     69   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
     70     eigen_assert((internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (sizemask)) == 0 \
     71               && "this assertion is explained here: " \
     72               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
     73               " **** READ THIS WEB PAGE !!! ****");
     74 #else
     75   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
     76     eigen_assert((internal::UIntPtr(array) & (sizemask)) == 0 \
     77               && "this assertion is explained here: " \
     78               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
     79               " **** READ THIS WEB PAGE !!! ****");
     80 #endif
     81 
     82 template <typename T, int Size, int MatrixOrArrayOptions>
     83 struct plain_array<T, Size, MatrixOrArrayOptions, 8>
     84 {
     85   EIGEN_ALIGN_TO_BOUNDARY(8) T array[Size];
     86 
     87   EIGEN_DEVICE_FUNC
     88   plain_array()
     89   {
     90     EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(7);
     91     check_static_allocation_size<T,Size>();
     92   }
     93 
     94   EIGEN_DEVICE_FUNC
     95   plain_array(constructor_without_unaligned_array_assert)
     96   {
     97     check_static_allocation_size<T,Size>();
     98   }
     99 };
    100 
    101 template <typename T, int Size, int MatrixOrArrayOptions>
    102 struct plain_array<T, Size, MatrixOrArrayOptions, 16>
    103 {
    104   EIGEN_ALIGN_TO_BOUNDARY(16) T array[Size];
    105 
    106   EIGEN_DEVICE_FUNC
    107   plain_array()
    108   {
    109     EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(15);
    110     check_static_allocation_size<T,Size>();
    111   }
    112 
    113   EIGEN_DEVICE_FUNC
    114   plain_array(constructor_without_unaligned_array_assert)
    115   {
    116     check_static_allocation_size<T,Size>();
    117   }
    118 };
    119 
    120 template <typename T, int Size, int MatrixOrArrayOptions>
    121 struct plain_array<T, Size, MatrixOrArrayOptions, 32>
    122 {
    123   EIGEN_ALIGN_TO_BOUNDARY(32) T array[Size];
    124 
    125   EIGEN_DEVICE_FUNC
    126   plain_array()
    127   {
    128     EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(31);
    129     check_static_allocation_size<T,Size>();
    130   }
    131 
    132   EIGEN_DEVICE_FUNC
    133   plain_array(constructor_without_unaligned_array_assert)
    134   {
    135     check_static_allocation_size<T,Size>();
    136   }
    137 };
    138 
    139 template <typename T, int Size, int MatrixOrArrayOptions>
    140 struct plain_array<T, Size, MatrixOrArrayOptions, 64>
    141 {
    142   EIGEN_ALIGN_TO_BOUNDARY(64) T array[Size];
    143 
    144   EIGEN_DEVICE_FUNC
    145   plain_array()
    146   {
    147     EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(63);
    148     check_static_allocation_size<T,Size>();
    149   }
    150 
    151   EIGEN_DEVICE_FUNC
    152   plain_array(constructor_without_unaligned_array_assert)
    153   {
    154     check_static_allocation_size<T,Size>();
    155   }
    156 };
    157 
    158 template <typename T, int MatrixOrArrayOptions, int Alignment>
    159 struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
    160 {
    161   T array[1];
    162   EIGEN_DEVICE_FUNC plain_array() {}
    163   EIGEN_DEVICE_FUNC plain_array(constructor_without_unaligned_array_assert) {}
    164 };
    165 
    166 } // end namespace internal
    167 
    168 /** \internal
    169   *
    170   * \class DenseStorage
    171   * \ingroup Core_Module
    172   *
    173   * \brief Stores the data of a matrix
    174   *
    175   * This class stores the data of fixed-size, dynamic-size or mixed matrices
    176   * in a way as compact as possible.
    177   *
    178   * \sa Matrix
    179   */
    180 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;
    181 
    182 // purely fixed-size matrix
    183 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage
    184 {
    185     internal::plain_array<T,Size,_Options> m_data;
    186   public:
    187     EIGEN_DEVICE_FUNC DenseStorage() {
    188       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
    189     }
    190     EIGEN_DEVICE_FUNC
    191     explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
    192       : m_data(internal::constructor_without_unaligned_array_assert()) {}
    193     EIGEN_DEVICE_FUNC
    194     DenseStorage(const DenseStorage& other) : m_data(other.m_data) {
    195       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
    196     }
    197     EIGEN_DEVICE_FUNC
    198     DenseStorage& operator=(const DenseStorage& other)
    199     {
    200       if (this != &other) m_data = other.m_data;
    201       return *this;
    202     }
    203     EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) {
    204       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    205       eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols);
    206       EIGEN_UNUSED_VARIABLE(size);
    207       EIGEN_UNUSED_VARIABLE(rows);
    208       EIGEN_UNUSED_VARIABLE(cols);
    209     }
    210     EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
    211     EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
    212     EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
    213     EIGEN_DEVICE_FUNC void conservativeResize(Index,Index,Index) {}
    214     EIGEN_DEVICE_FUNC void resize(Index,Index,Index) {}
    215     EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
    216     EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
    217 };
    218 
    219 // null matrix
    220 template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
    221 {
    222   public:
    223     EIGEN_DEVICE_FUNC DenseStorage() {}
    224     EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert) {}
    225     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage&) {}
    226     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage&) { return *this; }
    227     EIGEN_DEVICE_FUNC DenseStorage(Index,Index,Index) {}
    228     EIGEN_DEVICE_FUNC void swap(DenseStorage& ) {}
    229     EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
    230     EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
    231     EIGEN_DEVICE_FUNC void conservativeResize(Index,Index,Index) {}
    232     EIGEN_DEVICE_FUNC void resize(Index,Index,Index) {}
    233     EIGEN_DEVICE_FUNC const T *data() const { return 0; }
    234     EIGEN_DEVICE_FUNC T *data() { return 0; }
    235 };
    236 
    237 // more specializations for null matrices; these are necessary to resolve ambiguities
    238 template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options>
    239 : public DenseStorage<T, 0, 0, 0, _Options> { };
    240 
    241 template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options>
    242 : public DenseStorage<T, 0, 0, 0, _Options> { };
    243 
    244 template<typename T, int _Cols, int _Options> class DenseStorage<T, 0, Dynamic, _Cols, _Options>
    245 : public DenseStorage<T, 0, 0, 0, _Options> { };
    246 
    247 // dynamic-size matrix with fixed-size storage
    248 template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options>
    249 {
    250     internal::plain_array<T,Size,_Options> m_data;
    251     Index m_rows;
    252     Index m_cols;
    253   public:
    254     EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0), m_cols(0) {}
    255     EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
    256       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
    257     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
    258     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    259     {
    260       if (this != &other)
    261       {
    262         m_data = other.m_data;
    263         m_rows = other.m_rows;
    264         m_cols = other.m_cols;
    265       }
    266       return *this;
    267     }
    268     EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index cols) : m_rows(rows), m_cols(cols) {}
    269     EIGEN_DEVICE_FUNC void swap(DenseStorage& other)
    270     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
    271     EIGEN_DEVICE_FUNC Index rows() const {return m_rows;}
    272     EIGEN_DEVICE_FUNC Index cols() const {return m_cols;}
    273     EIGEN_DEVICE_FUNC void conservativeResize(Index, Index rows, Index cols) { m_rows = rows; m_cols = cols; }
    274     EIGEN_DEVICE_FUNC void resize(Index, Index rows, Index cols) { m_rows = rows; m_cols = cols; }
    275     EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
    276     EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
    277 };
    278 
    279 // dynamic-size matrix with fixed-size storage and fixed width
    280 template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options>
    281 {
    282     internal::plain_array<T,Size,_Options> m_data;
    283     Index m_rows;
    284   public:
    285     EIGEN_DEVICE_FUNC DenseStorage() : m_rows(0) {}
    286     EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
    287       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
    288     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
    289     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    290     {
    291       if (this != &other)
    292       {
    293         m_data = other.m_data;
    294         m_rows = other.m_rows;
    295       }
    296       return *this;
    297     }
    298     EIGEN_DEVICE_FUNC DenseStorage(Index, Index rows, Index) : m_rows(rows) {}
    299     EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
    300     EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
    301     EIGEN_DEVICE_FUNC Index cols(void) const {return _Cols;}
    302     EIGEN_DEVICE_FUNC void conservativeResize(Index, Index rows, Index) { m_rows = rows; }
    303     EIGEN_DEVICE_FUNC void resize(Index, Index rows, Index) { m_rows = rows; }
    304     EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
    305     EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
    306 };
    307 
    308 // dynamic-size matrix with fixed-size storage and fixed height
    309 template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options>
    310 {
    311     internal::plain_array<T,Size,_Options> m_data;
    312     Index m_cols;
    313   public:
    314     EIGEN_DEVICE_FUNC DenseStorage() : m_cols(0) {}
    315     EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
    316       : m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
    317     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
    318     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    319     {
    320       if (this != &other)
    321       {
    322         m_data = other.m_data;
    323         m_cols = other.m_cols;
    324       }
    325       return *this;
    326     }
    327     EIGEN_DEVICE_FUNC DenseStorage(Index, Index, Index cols) : m_cols(cols) {}
    328     EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
    329     EIGEN_DEVICE_FUNC Index rows(void) const {return _Rows;}
    330     EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
    331     void conservativeResize(Index, Index, Index cols) { m_cols = cols; }
    332     void resize(Index, Index, Index cols) { m_cols = cols; }
    333     EIGEN_DEVICE_FUNC const T *data() const { return m_data.array; }
    334     EIGEN_DEVICE_FUNC T *data() { return m_data.array; }
    335 };
    336 
    337 // purely dynamic matrix.
    338 template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options>
    339 {
    340     T *m_data;
    341     Index m_rows;
    342     Index m_cols;
    343   public:
    344     EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
    345     EIGEN_DEVICE_FUNC explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
    346        : m_data(0), m_rows(0), m_cols(0) {}
    347     EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols)
    348       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols)
    349     {
    350       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    351       eigen_internal_assert(size==rows*cols && rows>=0 && cols >=0);
    352     }
    353     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
    354       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(other.m_rows*other.m_cols))
    355       , m_rows(other.m_rows)
    356       , m_cols(other.m_cols)
    357     {
    358       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*m_cols)
    359       internal::smart_copy(other.m_data, other.m_data+other.m_rows*other.m_cols, m_data);
    360     }
    361     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    362     {
    363       if (this != &other)
    364       {
    365         DenseStorage tmp(other);
    366         this->swap(tmp);
    367       }
    368       return *this;
    369     }
    370 #if EIGEN_HAS_RVALUE_REFERENCES
    371     EIGEN_DEVICE_FUNC
    372     DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
    373       : m_data(std::move(other.m_data))
    374       , m_rows(std::move(other.m_rows))
    375       , m_cols(std::move(other.m_cols))
    376     {
    377       other.m_data = nullptr;
    378       other.m_rows = 0;
    379       other.m_cols = 0;
    380     }
    381     EIGEN_DEVICE_FUNC
    382     DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
    383     {
    384       using std::swap;
    385       swap(m_data, other.m_data);
    386       swap(m_rows, other.m_rows);
    387       swap(m_cols, other.m_cols);
    388       return *this;
    389     }
    390 #endif
    391     EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
    392     EIGEN_DEVICE_FUNC void swap(DenseStorage& other)
    393     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
    394     EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
    395     EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
    396     void conservativeResize(Index size, Index rows, Index cols)
    397     {
    398       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
    399       m_rows = rows;
    400       m_cols = cols;
    401     }
    402     EIGEN_DEVICE_FUNC void resize(Index size, Index rows, Index cols)
    403     {
    404       if(size != m_rows*m_cols)
    405       {
    406         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
    407         if (size)
    408           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
    409         else
    410           m_data = 0;
    411         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    412       }
    413       m_rows = rows;
    414       m_cols = cols;
    415     }
    416     EIGEN_DEVICE_FUNC const T *data() const { return m_data; }
    417     EIGEN_DEVICE_FUNC T *data() { return m_data; }
    418 };
    419 
    420 // matrix with dynamic width and fixed height (so that matrix has dynamic size).
    421 template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options>
    422 {
    423     T *m_data;
    424     Index m_cols;
    425   public:
    426     EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_cols(0) {}
    427     explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
    428     EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
    429     {
    430       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    431       eigen_internal_assert(size==rows*cols && rows==_Rows && cols >=0);
    432       EIGEN_UNUSED_VARIABLE(rows);
    433     }
    434     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
    435       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(_Rows*other.m_cols))
    436       , m_cols(other.m_cols)
    437     {
    438       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_cols*_Rows)
    439       internal::smart_copy(other.m_data, other.m_data+_Rows*m_cols, m_data);
    440     }
    441     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    442     {
    443       if (this != &other)
    444       {
    445         DenseStorage tmp(other);
    446         this->swap(tmp);
    447       }
    448       return *this;
    449     }
    450 #if EIGEN_HAS_RVALUE_REFERENCES
    451     EIGEN_DEVICE_FUNC
    452     DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
    453       : m_data(std::move(other.m_data))
    454       , m_cols(std::move(other.m_cols))
    455     {
    456       other.m_data = nullptr;
    457       other.m_cols = 0;
    458     }
    459     EIGEN_DEVICE_FUNC
    460     DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
    461     {
    462       using std::swap;
    463       swap(m_data, other.m_data);
    464       swap(m_cols, other.m_cols);
    465       return *this;
    466     }
    467 #endif
    468     EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
    469     EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
    470     EIGEN_DEVICE_FUNC static Index rows(void) {return _Rows;}
    471     EIGEN_DEVICE_FUNC Index cols(void) const {return m_cols;}
    472     EIGEN_DEVICE_FUNC void conservativeResize(Index size, Index, Index cols)
    473     {
    474       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
    475       m_cols = cols;
    476     }
    477     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index size, Index, Index cols)
    478     {
    479       if(size != _Rows*m_cols)
    480       {
    481         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
    482         if (size)
    483           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
    484         else
    485           m_data = 0;
    486         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    487       }
    488       m_cols = cols;
    489     }
    490     EIGEN_DEVICE_FUNC const T *data() const { return m_data; }
    491     EIGEN_DEVICE_FUNC T *data() { return m_data; }
    492 };
    493 
    494 // matrix with dynamic height and fixed width (so that matrix has dynamic size).
    495 template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options>
    496 {
    497     T *m_data;
    498     Index m_rows;
    499   public:
    500     EIGEN_DEVICE_FUNC DenseStorage() : m_data(0), m_rows(0) {}
    501     explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
    502     EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
    503     {
    504       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    505       eigen_internal_assert(size==rows*cols && rows>=0 && cols == _Cols);
    506       EIGEN_UNUSED_VARIABLE(cols);
    507     }
    508     EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
    509       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(other.m_rows*_Cols))
    510       , m_rows(other.m_rows)
    511     {
    512       EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*_Cols)
    513       internal::smart_copy(other.m_data, other.m_data+other.m_rows*_Cols, m_data);
    514     }
    515     EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
    516     {
    517       if (this != &other)
    518       {
    519         DenseStorage tmp(other);
    520         this->swap(tmp);
    521       }
    522       return *this;
    523     }
    524 #if EIGEN_HAS_RVALUE_REFERENCES
    525     EIGEN_DEVICE_FUNC
    526     DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT
    527       : m_data(std::move(other.m_data))
    528       , m_rows(std::move(other.m_rows))
    529     {
    530       other.m_data = nullptr;
    531       other.m_rows = 0;
    532     }
    533     EIGEN_DEVICE_FUNC
    534     DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT
    535     {
    536       using std::swap;
    537       swap(m_data, other.m_data);
    538       swap(m_rows, other.m_rows);
    539       return *this;
    540     }
    541 #endif
    542     EIGEN_DEVICE_FUNC ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
    543     EIGEN_DEVICE_FUNC void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
    544     EIGEN_DEVICE_FUNC Index rows(void) const {return m_rows;}
    545     EIGEN_DEVICE_FUNC static Index cols(void) {return _Cols;}
    546     void conservativeResize(Index size, Index rows, Index)
    547     {
    548       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
    549       m_rows = rows;
    550     }
    551     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(Index size, Index rows, Index)
    552     {
    553       if(size != m_rows*_Cols)
    554       {
    555         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
    556         if (size)
    557           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
    558         else
    559           m_data = 0;
    560         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    561       }
    562       m_rows = rows;
    563     }
    564     EIGEN_DEVICE_FUNC const T *data() const { return m_data; }
    565     EIGEN_DEVICE_FUNC T *data() { return m_data; }
    566 };
    567 
    568 } // end namespace Eigen
    569 
    570 #endif // EIGEN_MATRIX_H
    571