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 
00031 template <typename T, int Size, int MatrixOrArrayOptions,
00032           int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
00033                         : (((Size*sizeof(T))%16)==0) ? 16
00034                         : 0 >
00035 struct plain_array
00036 {
00037   T array[Size];
00038   plain_array() {}
00039   plain_array(constructor_without_unaligned_array_assert) {}
00040 };
00041 
00042 #if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
00043   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
00044 #elif EIGEN_GNUC_AT_LEAST(4,7) 
00045   // 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.
00046   // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
00047   // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
00048   template<typename PtrType>
00049   EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
00050   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
00051     eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & sizemask) == 0 \
00052               && "this assertion is explained here: " \
00053               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
00054               " **** READ THIS WEB PAGE !!! ****");
00055 #else
00056   #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
00057     eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
00058               && "this assertion is explained here: " \
00059               "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
00060               " **** READ THIS WEB PAGE !!! ****");
00061 #endif
00062 
00063 template <typename T, int Size, int MatrixOrArrayOptions>
00064 struct plain_array<T, Size, MatrixOrArrayOptions, 16>
00065 {
00066   EIGEN_USER_ALIGN16 T array[Size];
00067   plain_array() { EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf) }
00068   plain_array(constructor_without_unaligned_array_assert) {}
00069 };
00070 
00071 template <typename T, int MatrixOrArrayOptions, int Alignment>
00072 struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
00073 {
00074   EIGEN_USER_ALIGN16 T array[1];
00075   plain_array() {}
00076   plain_array(constructor_without_unaligned_array_assert) {}
00077 };
00078 
00079 } // end namespace internal
00080 
00093 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;
00094 
00095 // purely fixed-size matrix
00096 template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage
00097 {
00098     internal::plain_array<T,Size,_Options> m_data;
00099   public:
00100     inline explicit DenseStorage() {}
00101     inline DenseStorage(internal::constructor_without_unaligned_array_assert)
00102       : m_data(internal::constructor_without_unaligned_array_assert()) {}
00103     inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
00104     inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
00105     static inline DenseIndex rows(void) {return _Rows;}
00106     static inline DenseIndex cols(void) {return _Cols;}
00107     inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
00108     inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
00109     inline const T *data() const { return m_data.array; }
00110     inline T *data() { return m_data.array; }
00111 };
00112 
00113 // null matrix
00114 template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
00115 {
00116   public:
00117     inline explicit DenseStorage() {}
00118     inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
00119     inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
00120     inline void swap(DenseStorage& ) {}
00121     static inline DenseIndex rows(void) {return _Rows;}
00122     static inline DenseIndex cols(void) {return _Cols;}
00123     inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
00124     inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
00125     inline const T *data() const { return 0; }
00126     inline T *data() { return 0; }
00127 };
00128 
00129 // more specializations for null matrices; these are necessary to resolve ambiguities
00130 template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options>
00131 : public DenseStorage<T, 0, 0, 0, _Options> { };
00132 
00133 template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options>
00134 : public DenseStorage<T, 0, 0, 0, _Options> { };
00135 
00136 template<typename T, int _Cols, int _Options> class DenseStorage<T, 0, Dynamic, _Cols, _Options>
00137 : public DenseStorage<T, 0, 0, 0, _Options> { };
00138 
00139 // dynamic-size matrix with fixed-size storage
00140 template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options>
00141 {
00142     internal::plain_array<T,Size,_Options> m_data;
00143     DenseIndex m_rows;
00144     DenseIndex m_cols;
00145   public:
00146     inline explicit DenseStorage() : m_rows(0), m_cols(0) {}
00147     inline DenseStorage(internal::constructor_without_unaligned_array_assert)
00148       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
00149     inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex cols) : m_rows(rows), m_cols(cols) {}
00150     inline void swap(DenseStorage& other)
00151     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
00152     inline DenseIndex rows(void) const {return m_rows;}
00153     inline DenseIndex cols(void) const {return m_cols;}
00154     inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
00155     inline void resize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; }
00156     inline const T *data() const { return m_data.array; }
00157     inline T *data() { return m_data.array; }
00158 };
00159 
00160 // dynamic-size matrix with fixed-size storage and fixed width
00161 template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options>
00162 {
00163     internal::plain_array<T,Size,_Options> m_data;
00164     DenseIndex m_rows;
00165   public:
00166     inline explicit DenseStorage() : m_rows(0) {}
00167     inline DenseStorage(internal::constructor_without_unaligned_array_assert)
00168       : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
00169     inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex) : m_rows(rows) {}
00170     inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
00171     inline DenseIndex rows(void) const {return m_rows;}
00172     inline DenseIndex cols(void) const {return _Cols;}
00173     inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
00174     inline void resize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; }
00175     inline const T *data() const { return m_data.array; }
00176     inline T *data() { return m_data.array; }
00177 };
00178 
00179 // dynamic-size matrix with fixed-size storage and fixed height
00180 template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options>
00181 {
00182     internal::plain_array<T,Size,_Options> m_data;
00183     DenseIndex m_cols;
00184   public:
00185     inline explicit DenseStorage() : m_cols(0) {}
00186     inline DenseStorage(internal::constructor_without_unaligned_array_assert)
00187       : m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
00188     inline DenseStorage(DenseIndex, DenseIndex, DenseIndex cols) : m_cols(cols) {}
00189     inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
00190     inline DenseIndex rows(void) const {return _Rows;}
00191     inline DenseIndex cols(void) const {return m_cols;}
00192     inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
00193     inline void resize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; }
00194     inline const T *data() const { return m_data.array; }
00195     inline T *data() { return m_data.array; }
00196 };
00197 
00198 // purely dynamic matrix.
00199 template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options>
00200 {
00201     T *m_data;
00202     DenseIndex m_rows;
00203     DenseIndex m_cols;
00204   public:
00205     inline explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
00206     inline DenseStorage(internal::constructor_without_unaligned_array_assert)
00207        : m_data(0), m_rows(0), m_cols(0) {}
00208     inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex cols)
00209       : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols) 
00210     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00211     inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
00212     inline void swap(DenseStorage& other)
00213     { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
00214     inline DenseIndex rows(void) const {return m_rows;}
00215     inline DenseIndex cols(void) const {return m_cols;}
00216     inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex cols)
00217     {
00218       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
00219       m_rows = rows;
00220       m_cols = cols;
00221     }
00222     void resize(DenseIndex size, DenseIndex rows, DenseIndex cols)
00223     {
00224       if(size != m_rows*m_cols)
00225       {
00226         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
00227         if (size)
00228           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00229         else
00230           m_data = 0;
00231         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00232       }
00233       m_rows = rows;
00234       m_cols = cols;
00235     }
00236     inline const T *data() const { return m_data; }
00237     inline T *data() { return m_data; }
00238 };
00239 
00240 // matrix with dynamic width and fixed height (so that matrix has dynamic size).
00241 template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options>
00242 {
00243     T *m_data;
00244     DenseIndex m_cols;
00245   public:
00246     inline explicit DenseStorage() : m_data(0), m_cols(0) {}
00247     inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
00248     inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
00249     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00250     inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
00251     inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
00252     static inline DenseIndex rows(void) {return _Rows;}
00253     inline DenseIndex cols(void) const {return m_cols;}
00254     inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols)
00255     {
00256       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
00257       m_cols = cols;
00258     }
00259     EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex cols)
00260     {
00261       if(size != _Rows*m_cols)
00262       {
00263         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
00264         if (size)
00265           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00266         else
00267           m_data = 0;
00268         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00269       }
00270       m_cols = cols;
00271     }
00272     inline const T *data() const { return m_data; }
00273     inline T *data() { return m_data; }
00274 };
00275 
00276 // matrix with dynamic height and fixed width (so that matrix has dynamic size).
00277 template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options>
00278 {
00279     T *m_data;
00280     DenseIndex m_rows;
00281   public:
00282     inline explicit DenseStorage() : m_data(0), m_rows(0) {}
00283     inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
00284     inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
00285     { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
00286     inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
00287     inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
00288     inline DenseIndex rows(void) const {return m_rows;}
00289     static inline DenseIndex cols(void) {return _Cols;}
00290     inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex)
00291     {
00292       m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
00293       m_rows = rows;
00294     }
00295     EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex rows, DenseIndex)
00296     {
00297       if(size != m_rows*_Cols)
00298       {
00299         internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
00300         if (size)
00301           m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
00302         else
00303           m_data = 0;
00304         EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
00305       }
00306       m_rows = rows;
00307     }
00308     inline const T *data() const { return m_data; }
00309     inline T *data() { return m_data; }
00310 };
00311 
00312 } // end namespace Eigen
00313 
00314 #endif // EIGEN_MATRIX_H