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