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
21namespace Eigen {
22
23namespace internal {
24
25struct constructor_without_unaligned_array_assert {};
26
27template<typename T, int Size>
28EIGEN_DEVICE_FUNC
29void 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  */
41template <typename T, int Size, int MatrixOrArrayOptions,
42          int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
43                        : compute_default_alignment<T,Size>::value >
44struct 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
82template <typename T, int Size, int MatrixOrArrayOptions>
83struct 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
101template <typename T, int Size, int MatrixOrArrayOptions>
102struct 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
120template <typename T, int Size, int MatrixOrArrayOptions>
121struct 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
139template <typename T, int Size, int MatrixOrArrayOptions>
140struct 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
158template <typename T, int MatrixOrArrayOptions, int Alignment>
159struct 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  */
180template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;
181
182// purely fixed-size matrix
183template<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
220template<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
238template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options>
239: public DenseStorage<T, 0, 0, 0, _Options> { };
240
241template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options>
242: public DenseStorage<T, 0, 0, 0, _Options> { };
243
244template<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
248template<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
280template<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
309template<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.
338template<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).
421template<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).
495template<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