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@inria.fr>
5 // Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6 // Copyright (C) 2010-2013 Hauke Heibel <hauke.heibel@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
check_static_allocation_size()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
plain_arrayplain_array49   plain_array()
50   {
51     check_static_allocation_size<T,Size>();
52   }
53 
54   EIGEN_DEVICE_FUNC
plain_arrayplain_array55   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>
eigen_unaligned_array_assert_workaround_gcc47(PtrType array)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