DenseStorage.h 14.4 KB
Newer Older
LM's avatar
LM committed
1 2 3 4 5 6 7
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
Don Gagne's avatar
Don Gagne committed
8 9 10
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
LM's avatar
LM committed
11 12 13 14 15 16 17 18 19 20

#ifndef EIGEN_MATRIXSTORAGE_H
#define EIGEN_MATRIXSTORAGE_H

#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
  #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
#else
  #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
#endif

Don Gagne's avatar
Don Gagne committed
21 22
namespace Eigen {

LM's avatar
LM committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
namespace internal {

struct constructor_without_unaligned_array_assert {};

/** \internal
  * Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned:
  * to 16 bytes boundary if the total size is a multiple of 16 bytes.
  */
template <typename T, int Size, int MatrixOrArrayOptions,
          int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0
                        : (((Size*sizeof(T))%16)==0) ? 16
                        : 0 >
struct plain_array
{
  T array[Size];
Don Gagne's avatar
Don Gagne committed
38 39 40 41 42 43 44 45 46 47

  plain_array() 
  { 
    EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
  }

  plain_array(constructor_without_unaligned_array_assert) 
  { 
    EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
  }
LM's avatar
LM committed
48 49
};

Don Gagne's avatar
Don Gagne committed
50
#if defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
LM's avatar
LM committed
51
  #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask)
Don Gagne's avatar
Don Gagne committed
52 53 54 55 56 57 58 59 60 61 62
#elif EIGEN_GNUC_AT_LEAST(4,7) 
  // 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.
  // See this bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53900
  // Hiding the origin of the array pointer behind a function argument seems to do the trick even if the function is inlined:
  template<typename PtrType>
  EIGEN_ALWAYS_INLINE PtrType eigen_unaligned_array_assert_workaround_gcc47(PtrType array) { return array; }
  #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
    eigen_assert((reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & sizemask) == 0 \
              && "this assertion is explained here: " \
              "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
              " **** READ THIS WEB PAGE !!! ****");
LM's avatar
LM committed
63 64 65 66
#else
  #define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \
    eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \
              && "this assertion is explained here: " \
Don Gagne's avatar
Don Gagne committed
67
              "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" \
LM's avatar
LM committed
68 69 70 71 72 73 74
              " **** READ THIS WEB PAGE !!! ****");
#endif

template <typename T, int Size, int MatrixOrArrayOptions>
struct plain_array<T, Size, MatrixOrArrayOptions, 16>
{
  EIGEN_USER_ALIGN16 T array[Size];
Don Gagne's avatar
Don Gagne committed
75 76 77 78 79 80 81 82 83 84 85

  plain_array() 
  { 
    EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf);
    EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
  }

  plain_array(constructor_without_unaligned_array_assert) 
  { 
    EIGEN_STATIC_ASSERT(Size * sizeof(T) <= 128 * 128 * 8, OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG);
  }
LM's avatar
LM committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
};

template <typename T, int MatrixOrArrayOptions, int Alignment>
struct plain_array<T, 0, MatrixOrArrayOptions, Alignment>
{
  EIGEN_USER_ALIGN16 T array[1];
  plain_array() {}
  plain_array(constructor_without_unaligned_array_assert) {}
};

} // end namespace internal

/** \internal
  *
  * \class DenseStorage
  * \ingroup Core_Module
  *
  * \brief Stores the data of a matrix
  *
  * This class stores the data of fixed-size, dynamic-size or mixed matrices
  * in a way as compact as possible.
  *
  * \sa Matrix
  */
template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage;

// purely fixed-size matrix
template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage
{
    internal::plain_array<T,Size,_Options> m_data;
  public:
Don Gagne's avatar
Don Gagne committed
117
    inline DenseStorage() {}
LM's avatar
LM committed
118 119 120 121
    inline DenseStorage(internal::constructor_without_unaligned_array_assert)
      : m_data(internal::constructor_without_unaligned_array_assert()) {}
    inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
    inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); }
Don Gagne's avatar
Don Gagne committed
122 123
    static inline DenseIndex rows(void) {return _Rows;}
    static inline DenseIndex cols(void) {return _Cols;}
LM's avatar
LM committed
124 125 126 127 128 129 130 131 132 133
    inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
    inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
    inline const T *data() const { return m_data.array; }
    inline T *data() { return m_data.array; }
};

// null matrix
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options>
{
  public:
Don Gagne's avatar
Don Gagne committed
134
    inline DenseStorage() {}
LM's avatar
LM committed
135 136 137
    inline DenseStorage(internal::constructor_without_unaligned_array_assert) {}
    inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {}
    inline void swap(DenseStorage& ) {}
Don Gagne's avatar
Don Gagne committed
138 139
    static inline DenseIndex rows(void) {return _Rows;}
    static inline DenseIndex cols(void) {return _Cols;}
LM's avatar
LM committed
140 141 142 143 144 145
    inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {}
    inline void resize(DenseIndex,DenseIndex,DenseIndex) {}
    inline const T *data() const { return 0; }
    inline T *data() { return 0; }
};

Don Gagne's avatar
Don Gagne committed
146 147 148 149 150 151 152 153 154 155
// more specializations for null matrices; these are necessary to resolve ambiguities
template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options>
: public DenseStorage<T, 0, 0, 0, _Options> { };

template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options>
: public DenseStorage<T, 0, 0, 0, _Options> { };

template<typename T, int _Cols, int _Options> class DenseStorage<T, 0, Dynamic, _Cols, _Options>
: public DenseStorage<T, 0, 0, 0, _Options> { };

LM's avatar
LM committed
156 157 158 159 160 161 162
// dynamic-size matrix with fixed-size storage
template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options>
{
    internal::plain_array<T,Size,_Options> m_data;
    DenseIndex m_rows;
    DenseIndex m_cols;
  public:
Don Gagne's avatar
Don Gagne committed
163
    inline DenseStorage() : m_rows(0), m_cols(0) {}
LM's avatar
LM committed
164 165
    inline DenseStorage(internal::constructor_without_unaligned_array_assert)
      : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {}
Don Gagne's avatar
Don Gagne committed
166
    inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) : m_rows(nbRows), m_cols(nbCols) {}
LM's avatar
LM committed
167 168
    inline void swap(DenseStorage& other)
    { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
Don Gagne's avatar
Don Gagne committed
169 170 171 172
    inline DenseIndex rows() const {return m_rows;}
    inline DenseIndex cols() const {return m_cols;}
    inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
    inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex nbCols) { m_rows = nbRows; m_cols = nbCols; }
LM's avatar
LM committed
173 174 175 176 177 178 179 180 181 182
    inline const T *data() const { return m_data.array; }
    inline T *data() { return m_data.array; }
};

// dynamic-size matrix with fixed-size storage and fixed width
template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options>
{
    internal::plain_array<T,Size,_Options> m_data;
    DenseIndex m_rows;
  public:
Don Gagne's avatar
Don Gagne committed
183
    inline DenseStorage() : m_rows(0) {}
LM's avatar
LM committed
184 185
    inline DenseStorage(internal::constructor_without_unaligned_array_assert)
      : m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {}
Don Gagne's avatar
Don Gagne committed
186
    inline DenseStorage(DenseIndex, DenseIndex nbRows, DenseIndex) : m_rows(nbRows) {}
LM's avatar
LM committed
187 188 189
    inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
    inline DenseIndex rows(void) const {return m_rows;}
    inline DenseIndex cols(void) const {return _Cols;}
Don Gagne's avatar
Don Gagne committed
190 191
    inline void conservativeResize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
    inline void resize(DenseIndex, DenseIndex nbRows, DenseIndex) { m_rows = nbRows; }
LM's avatar
LM committed
192 193 194 195 196 197 198 199 200 201
    inline const T *data() const { return m_data.array; }
    inline T *data() { return m_data.array; }
};

// dynamic-size matrix with fixed-size storage and fixed height
template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options>
{
    internal::plain_array<T,Size,_Options> m_data;
    DenseIndex m_cols;
  public:
Don Gagne's avatar
Don Gagne committed
202
    inline DenseStorage() : m_cols(0) {}
LM's avatar
LM committed
203 204
    inline DenseStorage(internal::constructor_without_unaligned_array_assert)
      : m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {}
Don Gagne's avatar
Don Gagne committed
205
    inline DenseStorage(DenseIndex, DenseIndex, DenseIndex nbCols) : m_cols(nbCols) {}
LM's avatar
LM committed
206 207 208
    inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
    inline DenseIndex rows(void) const {return _Rows;}
    inline DenseIndex cols(void) const {return m_cols;}
Don Gagne's avatar
Don Gagne committed
209 210
    inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
    inline void resize(DenseIndex, DenseIndex, DenseIndex nbCols) { m_cols = nbCols; }
LM's avatar
LM committed
211 212 213 214 215 216 217 218 219 220 221
    inline const T *data() const { return m_data.array; }
    inline T *data() { return m_data.array; }
};

// purely dynamic matrix.
template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options>
{
    T *m_data;
    DenseIndex m_rows;
    DenseIndex m_cols;
  public:
Don Gagne's avatar
Don Gagne committed
222
    inline DenseStorage() : m_data(0), m_rows(0), m_cols(0) {}
LM's avatar
LM committed
223 224
    inline DenseStorage(internal::constructor_without_unaligned_array_assert)
       : m_data(0), m_rows(0), m_cols(0) {}
Don Gagne's avatar
Don Gagne committed
225 226
    inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
      : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows), m_cols(nbCols)
LM's avatar
LM committed
227 228 229 230 231 232
    { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
    inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); }
    inline void swap(DenseStorage& other)
    { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); }
    inline DenseIndex rows(void) const {return m_rows;}
    inline DenseIndex cols(void) const {return m_cols;}
Don Gagne's avatar
Don Gagne committed
233
    inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
LM's avatar
LM committed
234 235
    {
      m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols);
Don Gagne's avatar
Don Gagne committed
236 237
      m_rows = nbRows;
      m_cols = nbCols;
LM's avatar
LM committed
238
    }
Don Gagne's avatar
Don Gagne committed
239
    void resize(DenseIndex size, DenseIndex nbRows, DenseIndex nbCols)
LM's avatar
LM committed
240 241 242 243 244 245 246 247 248 249
    {
      if(size != m_rows*m_cols)
      {
        internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols);
        if (size)
          m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
        else
          m_data = 0;
        EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
      }
Don Gagne's avatar
Don Gagne committed
250 251
      m_rows = nbRows;
      m_cols = nbCols;
LM's avatar
LM committed
252 253 254 255 256 257 258 259 260 261 262
    }
    inline const T *data() const { return m_data; }
    inline T *data() { return m_data; }
};

// matrix with dynamic width and fixed height (so that matrix has dynamic size).
template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options>
{
    T *m_data;
    DenseIndex m_cols;
  public:
Don Gagne's avatar
Don Gagne committed
263
    inline DenseStorage() : m_data(0), m_cols(0) {}
LM's avatar
LM committed
264
    inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
Don Gagne's avatar
Don Gagne committed
265
    inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex nbCols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(nbCols)
LM's avatar
LM committed
266 267 268
    { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
    inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); }
    inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); }
Don Gagne's avatar
Don Gagne committed
269
    static inline DenseIndex rows(void) {return _Rows;}
LM's avatar
LM committed
270
    inline DenseIndex cols(void) const {return m_cols;}
Don Gagne's avatar
Don Gagne committed
271
    inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex nbCols)
LM's avatar
LM committed
272 273
    {
      m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols);
Don Gagne's avatar
Don Gagne committed
274
      m_cols = nbCols;
LM's avatar
LM committed
275
    }
Don Gagne's avatar
Don Gagne committed
276
    EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex nbCols)
LM's avatar
LM committed
277 278 279 280 281 282 283 284 285 286
    {
      if(size != _Rows*m_cols)
      {
        internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols);
        if (size)
          m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
        else
          m_data = 0;
        EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
      }
Don Gagne's avatar
Don Gagne committed
287
      m_cols = nbCols;
LM's avatar
LM committed
288 289 290 291 292 293 294 295 296 297 298
    }
    inline const T *data() const { return m_data; }
    inline T *data() { return m_data; }
};

// matrix with dynamic height and fixed width (so that matrix has dynamic size).
template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options>
{
    T *m_data;
    DenseIndex m_rows;
  public:
Don Gagne's avatar
Don Gagne committed
299
    inline DenseStorage() : m_data(0), m_rows(0) {}
LM's avatar
LM committed
300
    inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
Don Gagne's avatar
Don Gagne committed
301
    inline DenseStorage(DenseIndex size, DenseIndex nbRows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(nbRows)
LM's avatar
LM committed
302 303 304 305
    { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN }
    inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); }
    inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); }
    inline DenseIndex rows(void) const {return m_rows;}
Don Gagne's avatar
Don Gagne committed
306 307
    static inline DenseIndex cols(void) {return _Cols;}
    inline void conservativeResize(DenseIndex size, DenseIndex nbRows, DenseIndex)
LM's avatar
LM committed
308 309
    {
      m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols);
Don Gagne's avatar
Don Gagne committed
310
      m_rows = nbRows;
LM's avatar
LM committed
311
    }
Don Gagne's avatar
Don Gagne committed
312
    EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex nbRows, DenseIndex)
LM's avatar
LM committed
313 314 315 316 317 318 319 320 321 322
    {
      if(size != m_rows*_Cols)
      {
        internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows);
        if (size)
          m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
        else
          m_data = 0;
        EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
      }
Don Gagne's avatar
Don Gagne committed
323
      m_rows = nbRows;
LM's avatar
LM committed
324 325 326 327 328
    }
    inline const T *data() const { return m_data; }
    inline T *data() { return m_data; }
};

Don Gagne's avatar
Don Gagne committed
329 330
} // end namespace Eigen

LM's avatar
LM committed
331
#endif // EIGEN_MATRIX_H