Eigne Matrix Class Library

Dependents:   Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DenseStorage.h Source File

DenseStorage.h

00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
00007 //
00008 // This Source Code Form is subject to the terms of the Mozilla
00009 // Public License v. 2.0. If a copy of the MPL was not distributed
00010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00011 
00012 #ifndef EIGEN_MATRIXSTORAGE_H
00013 #define EIGEN_MATRIXSTORAGE_H
00014 
00015 #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
00016   #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
00017 #else
00018   #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00019 #endif
00020 
00021 namespace Eigen {
00022 
00023 namespace internal {
00024 
00025 struct constructor_without_unaligned_array_assert {};
00026 
00027 template<typename T, int Size> void check_static_allocation_size()
00028 {
00029   // if EIGEN_STACK_ALLOCATION_LIMIT is defined to 0, then no limit
00030   #if EIGEN_STACK_ALLOCATION_LIMIT
00031   EIGEN_STATIC_ASSERT(Size * sizeof(T) <= EIGEN_STACK_ALLOCATION_LIMIT, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
00032   #endif
00033 }
00034 
00035 /** \internal
00036   * Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
00037   * to 16 bytes boundary if the total size is a multiple of 16 bytes.
00038   */
00039 template <typename T, int Size, int MatrixOrArrayOptions,
00040           int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
00041                         : (((Size*sizeof(T))%16)==0) ? 16
00042                         : 0 >
00043 struct plain_array
00044 {
00045   T array[Size];
00046 
00047   plain_array() 
00048   { 
00049     check_static_allocation_size<T,Size>();
00050   }
00051 
00052   plain_array(constructor_without_unaligned_array_assert) 
00053   { 
00054     check_static_allocation_size<T,Size>();
00055   }
00056 };
00057 
00058 #if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
00059   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
00060 #elif EIGEN_GNUC_AT_LEAST(4,7) 
00061   // 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.
00062   // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
00063   // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
00064   template<typename PtrType>
00065   EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
00066   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
00067     eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & sizemask) == 0 \
00068               && "this assertion is explained here: " \
00069               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
00070               " **** READ THIS WEB PAGE !!! ****");
00071 #else
00072   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
00073     eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
00074               && "this assertion is explained here: " \
00075               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
00076               " **** READ THIS WEB PAGE !!! ****");
00077 #endif
00078 
00079 template <typename T, int Size, int MatrixOrArrayOptions>
00080 struct plain_array<T, Size, MatrixOrArrayOptions, 16>
00081 {
00082   EIGEN_USER_ALIGN16 T array[Size];
00083 
00084   plain_array() 
00085   { 
00086     EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
00087     check_static_allocation_size<T,Size>();
00088   }
00089 
00090   plain_array(constructor_without_unaligned_array_assert) 
00091   { 
00092     check_static_allocation_size<T,Size>();
00093   }
00094 };
00095 
00096 template <typename T, int MatrixOrArrayOptions, int Alignment>
00097 struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
00098 {
00099   EIGEN_USER_ALIGN16 T array[1];
00100   plain_array() {}
00101   plain_array(constructor_without_unaligned_array_assert) {}
00102 };
00103 
00104 } // end namespace internal
00105 
00106 /** \internal
00107   *
00108   * \class DenseStorage
00109   * \ingroup Core_Module
00110   *
00111   * \brief Stores the data of a matrix
00112   *
00113   * This class stores the data of fixed-size, dynamic-size or mixed matrices
00114   * in a way as compact as possible.
00115   *
00116   * \sa Matrix
00117   */
00118 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;
00119 
00120 // purely fixed-size matrix
00121 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage
00122 {
00123     internal::plain_array<T,Size,_Options> m_data;
00124   public:
00125     DenseStorage() {}
00126     DenseStorage(internal::constructor_without_unaligned_array_assert)
00127       : m_data(internal::constructor_without_unaligned_array_assert()) {}
00128     DenseStorage(const DenseStorage& other) : m_data(other.m_data) {}
00129     DenseStorage& operator=(const DenseStorage& other)
00130     {
00131       if (this != &other) m_data = other.m_data;
00132       return *this;
00133     }
00134     DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
00135     void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
00136     static DenseIndex rows(void) {return _Rows;}
00137     static DenseIndex cols(void) {return _Cols;}
00138     void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
00139     void resize(DenseIndex,DenseIndex,DenseIndex) {}
00140     const T *data() const { return m_data.array; }
00141     T *data() { return m_data.array; }
00142 };
00143 
00144 // null matrix
00145 template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
00146 {
00147   public:
00148     DenseStorage() {}
00149     DenseStorage(internal::constructor_without_unaligned_array_assert) {}
00150     DenseStorage(const DenseStorage&) {}
00151     DenseStorage& operator=(const DenseStorage&) { return *this; }
00152     DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
00153     void swap(DenseStorage& ) {}
00154     static DenseIndex rows(void) {return _Rows;}
00155     static DenseIndex cols(void) {return _Cols;}
00156     void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
00157     void resize(DenseIndex,DenseIndex,DenseIndex) {}
00158     const T *data() const { return 0; }
00159     T *data() { return 0; }
00160 };
00161 
00162 // more specializations for null matrices; these are necessary to resolve ambiguities
00163 template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options>
00164 : public DenseStorage<T, 0, 0, 0, _Options> { };
00165 
00166 template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options>
00167 : public DenseStorage<T, 0, 0, 0, _Options> { };
00168 
00169 template<typename T, int _Cols, int _Options> class DenseStorage<T, 0, Dynamic, _Cols, _Options>
00170 : public DenseStorage<T, 0, 0, 0, _Options> { };
00171 
00172 // dynamic-size matrix with fixed-size storage
00173 template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options>
00174 {
00175     internal::plain_array<T,Size,_Options> m_data;
00176     DenseIndex m_rows;
00177     DenseIndex m_cols;
00178   public:
00179     DenseStorage() : m_rows(0), m_cols(0) {}
00180     DenseStorage(internal::constructor_without_unaligned_array_assert)
00181       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
00182     DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows), m_cols(other.m_cols) {}
00183     DenseStorage& operator=(const DenseStorage& other)
00184     {
00185       if (this != &other)
00186       {
00187         m_data = other.m_data;
00188         m_rows = other.m_rows;
00189         m_cols = other.m_cols;
00190       }
00191       return *this;
00192     }
00193     DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
00194     void swap(DenseStorage& other)
00195     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
00196     DenseIndex rows() const {return m_rows;}
00197     DenseIndex cols() const {return m_cols;}
00198     void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
00199     void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
00200     const T *data() const { return m_data.array; }
00201     T *data() { return m_data.array; }
00202 };
00203 
00204 // dynamic-size matrix with fixed-size storage and fixed width
00205 template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options>
00206 {
00207     internal::plain_array<T,Size,_Options> m_data;
00208     DenseIndex m_rows;
00209   public:
00210     DenseStorage() : m_rows(0) {}
00211     DenseStorage(internal::constructor_without_unaligned_array_assert)
00212       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
00213     DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_rows(other.m_rows) {}
00214     DenseStorage& operator=(const DenseStorage& other)
00215     {
00216       if (this != &other)
00217       {
00218         m_data = other.m_data;
00219         m_rows = other.m_rows;
00220       }
00221       return *this;
00222     }
00223     DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
00224     void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
00225     DenseIndex rows(void) const {return m_rows;}
00226     DenseIndex cols(void) const {return _Cols;}
00227     void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
00228     void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
00229     const T *data() const { return m_data.array; }
00230     T *data() { return m_data.array; }
00231 };
00232 
00233 // dynamic-size matrix with fixed-size storage and fixed height
00234 template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options>
00235 {
00236     internal::plain_array<T,Size,_Options> m_data;
00237     DenseIndex m_cols;
00238   public:
00239     DenseStorage() : m_cols(0) {}
00240     DenseStorage(internal::constructor_without_unaligned_array_assert)
00241       : m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
00242     DenseStorage(const DenseStorage& other) : m_data(other.m_data), m_cols(other.m_cols) {}
00243     DenseStorage& operator=(const DenseStorage& other)
00244     {
00245       if (this != &other)
00246       {
00247         m_data = other.m_data;
00248         m_cols = other.m_cols;
00249       }
00250       return *this;
00251     }
00252     DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
00253     void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
00254     DenseIndex rows(void) const {return _Rows;}
00255     DenseIndex cols(void) const {return m_cols;}
00256     void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
00257     void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
00258     const T *data() const { return m_data.array; }
00259     T *data() { return m_data.array; }
00260 };
00261 
00262 // purely dynamic matrix.
00263 template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options>
00264 {
00265     T *m_data;
00266     DenseIndex m_rows;
00267     DenseIndex m_cols;
00268   public:
00269     DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
00270     DenseStorage(internal::constructor_without_unaligned_array_assert)
00271        : m_data(0), m_rows(0), m_cols(0) {}
00272     DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
00273       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
00274     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00275 #ifdef EIGEN_HAVE_RVALUE_REFERENCES
00276     DenseStorage(DenseStorage&& other)
00277       : m_data(std::move(other.m_data))
00278       , m_rows(std::move(other.m_rows))
00279       , m_cols(std::move(other.m_cols))
00280     {
00281       other.m_data = nullptr;
00282     }
00283     DenseStorage& operator=(DenseStorage&& other)
00284     {
00285       using std::swap;
00286       swap(m_data, other.m_data);
00287       swap(m_rows, other.m_rows);
00288       swap(m_cols, other.m_cols);
00289       return *this;
00290     }
00291 #endif
00292     ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
00293     void swap(DenseStorage& other)
00294     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
00295     DenseIndex rows(void) const {return m_rows;}
00296     DenseIndex cols(void) const {return m_cols;}
00297     void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
00298     {
00299       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
00300       m_rows = nbRows;
00301       m_cols = nbCols;
00302     }
00303     void resize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
00304     {
00305       if(size != m_rows*m_cols)
00306       {
00307         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
00308         if (size)
00309           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00310         else
00311           m_data = 0;
00312         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00313       }
00314       m_rows = nbRows;
00315       m_cols = nbCols;
00316     }
00317     const T *data() const { return m_data; }
00318     T *data() { return m_data; }
00319   private:
00320     DenseStorage(const DenseStorage&);
00321     DenseStorage& operator=(const DenseStorage&);
00322 };
00323 
00324 // matrix with dynamic width and fixed height (so that matrix has dynamic size).
00325 template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options>
00326 {
00327     T *m_data;
00328     DenseIndex m_cols;
00329   public:
00330     DenseStorage() : m_data(0), m_cols(0) {}
00331     DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
00332     DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
00333     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00334 #ifdef EIGEN_HAVE_RVALUE_REFERENCES
00335     DenseStorage(DenseStorage&& other)
00336       : m_data(std::move(other.m_data))
00337       , m_cols(std::move(other.m_cols))
00338     {
00339       other.m_data = nullptr;
00340     }
00341     DenseStorage& operator=(DenseStorage&& other)
00342     {
00343       using std::swap;
00344       swap(m_data, other.m_data);
00345       swap(m_cols, other.m_cols);
00346       return *this;
00347     }
00348 #endif
00349     ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
00350     void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
00351     static DenseIndex rows(void) {return _Rows;}
00352     DenseIndex cols(void) const {return m_cols;}
00353     void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
00354     {
00355       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
00356       m_cols = nbCols;
00357     }
00358     EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex nbCols)
00359     {
00360       if(size != _Rows*m_cols)
00361       {
00362         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
00363         if (size)
00364           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00365         else
00366           m_data = 0;
00367         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00368       }
00369       m_cols = nbCols;
00370     }
00371     const T *data() const { return m_data; }
00372     T *data() { return m_data; }
00373   private:
00374     DenseStorage(const DenseStorage&);
00375     DenseStorage& operator=(const DenseStorage&);
00376 };
00377 
00378 // matrix with dynamic height and fixed width (so that matrix has dynamic size).
00379 template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options>
00380 {
00381     T *m_data;
00382     DenseIndex m_rows;
00383   public:
00384     DenseStorage() : m_data(0), m_rows(0) {}
00385     DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
00386     DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
00387     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00388 #ifdef EIGEN_HAVE_RVALUE_REFERENCES
00389     DenseStorage(DenseStorage&& other)
00390       : m_data(std::move(other.m_data))
00391       , m_rows(std::move(other.m_rows))
00392     {
00393       other.m_data = nullptr;
00394     }
00395     DenseStorage& operator=(DenseStorage&& other)
00396     {
00397       using std::swap;
00398       swap(m_data, other.m_data);
00399       swap(m_rows, other.m_rows);
00400       return *this;
00401     }
00402 #endif
00403     ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
00404     void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
00405     DenseIndex rows(void) const {return m_rows;}
00406     static DenseIndex cols(void) {return _Cols;}
00407     void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
00408     {
00409       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
00410       m_rows = nbRows;
00411     }
00412     EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex nbRows, DenseIndex)
00413     {
00414       if(size != m_rows*_Cols)
00415       {
00416         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
00417         if (size)
00418           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00419         else
00420           m_data = 0;
00421         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00422       }
00423       m_rows = nbRows;
00424     }
00425     const T *data() const { return m_data; }
00426     T *data() { return m_data; }
00427   private:
00428     DenseStorage(const DenseStorage&);
00429     DenseStorage& operator=(const DenseStorage&);
00430 };
00431 
00432 } // end namespace Eigen
00433 
00434 #endif // EIGEN_MATRIX_H