mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-03-25 18:50:40 +08:00
Patch by Gael Guennebaud:
Rework the matrix storage to ensure optimal sizeof in all cases, while keeping the decoupling of matrix sizes versus storage sizes. Also fixing (recently introduced) bugs caused by unwanted reallocations of the buffers.
This commit is contained in:
parent
3698d8cf33
commit
aa8e2bcbde
@ -14,6 +14,7 @@ namespace Eigen {
|
||||
#include "src/Core/Coeffs.h"
|
||||
#include "src/Core/OperatorEquals.h"
|
||||
#include "src/Core/MatrixRef.h"
|
||||
#include "src/Core/MatrixStorage.h"
|
||||
#include "src/Core/Matrix.h"
|
||||
#include "src/Core/Cast.h"
|
||||
#include "src/Core/Eval.h"
|
||||
|
@ -187,7 +187,7 @@ Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>::map(Scalar* da
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
|
||||
::Matrix(const Scalar *data, int rows, int cols)
|
||||
: m_rows(rows), m_cols(cols), m_array(rows*cols)
|
||||
: m_storage(rows*cols, rows, cols)
|
||||
{
|
||||
*this = map(data, rows, cols);
|
||||
}
|
||||
@ -205,9 +205,7 @@ Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
|
||||
Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
|
||||
::Matrix(const Scalar *data, int size)
|
||||
: m_rows(RowsAtCompileTime == 1 ? 1 : size),
|
||||
m_cols(ColsAtCompileTime == 1 ? 1 : size),
|
||||
m_array(size)
|
||||
: m_storage(size, RowsAtCompileTime == 1 ? 1 : size, ColsAtCompileTime == 1 ? 1 : size)
|
||||
{
|
||||
*this = map(data, size);
|
||||
}
|
||||
|
@ -25,31 +25,6 @@
|
||||
#ifndef EIGEN_MATRIX_H
|
||||
#define EIGEN_MATRIX_H
|
||||
|
||||
template<typename T, int Size> class Array
|
||||
{
|
||||
T m_data[Size];
|
||||
public:
|
||||
Array() {}
|
||||
explicit Array(int) {}
|
||||
void resize(int) {}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
template<typename T> class Array<T, Dynamic>
|
||||
{
|
||||
T *m_data;
|
||||
public:
|
||||
explicit Array(int size) : m_data(new T[size]) {}
|
||||
~Array() { delete[] m_data; }
|
||||
void resize(int size)
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = new T[size];
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
/** \class Matrix
|
||||
*
|
||||
@ -123,38 +98,36 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
: _MaxRows * _MaxCols
|
||||
};
|
||||
|
||||
IntAtRunTimeIfDynamic<RowsAtCompileTime> m_rows;
|
||||
IntAtRunTimeIfDynamic<ColsAtCompileTime> m_cols;
|
||||
Array<Scalar, MaxSizeAtCompileTime> m_array;
|
||||
MatrixStorage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime> m_storage;
|
||||
|
||||
Ref _ref() const { return Ref(*this); }
|
||||
int _rows() const { return m_rows.value(); }
|
||||
int _cols() const { return m_cols.value(); }
|
||||
int _rows() const { return m_storage.rows(); }
|
||||
int _cols() const { return m_storage.cols(); }
|
||||
|
||||
const Scalar& _coeff(int row, int col) const
|
||||
{
|
||||
if(StorageOrder == ColumnMajor)
|
||||
return m_array.data()[row + col * m_rows.value()];
|
||||
return m_storage.data()[row + col * m_storage.rows()];
|
||||
else // RowMajor
|
||||
return m_array.data()[col + row * m_cols.value()];
|
||||
return m_storage.data()[col + row * m_storage.cols()];
|
||||
}
|
||||
|
||||
Scalar& _coeffRef(int row, int col)
|
||||
{
|
||||
if(StorageOrder == ColumnMajor)
|
||||
return m_array.data()[row + col * m_rows.value()];
|
||||
return m_storage.data()[row + col * m_storage.rows()];
|
||||
else // RowMajor
|
||||
return m_array.data()[col + row * m_cols.value()];
|
||||
return m_storage.data()[col + row * m_storage.cols()];
|
||||
}
|
||||
|
||||
public:
|
||||
/** \returns a const pointer to the data array of this matrix */
|
||||
const Scalar *data() const
|
||||
{ return m_array.data(); }
|
||||
{ return m_storage.data(); }
|
||||
|
||||
/** \returns a pointer to the data array of this matrix */
|
||||
Scalar *data()
|
||||
{ return m_array.data(); }
|
||||
{ return m_storage.data(); }
|
||||
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
@ -164,9 +137,7 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
&& cols > 0
|
||||
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
|
||||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
|
||||
m_rows.setValue(rows);
|
||||
m_cols.setValue(cols);
|
||||
m_array.resize(rows * cols);
|
||||
m_storage.resize(rows * cols, rows, cols);
|
||||
}
|
||||
|
||||
/** Copies the value of the expression \a other into *this.
|
||||
@ -229,9 +200,7 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
* it is redundant to pass the dimension here, so it makes more sense to use the default
|
||||
* constructor Matrix() instead.
|
||||
*/
|
||||
explicit Matrix(int dim) : m_rows(RowsAtCompileTime == 1 ? 1 : dim),
|
||||
m_cols(ColsAtCompileTime == 1 ? 1 : dim),
|
||||
m_array(dim)
|
||||
explicit Matrix(int dim) : m_storage(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
|
||||
{
|
||||
assert(dim > 0);
|
||||
assert((RowsAtCompileTime == 1
|
||||
@ -250,13 +219,13 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
* it is redundant to pass these parameters, so one should use the default constructor
|
||||
* Matrix() instead.
|
||||
*/
|
||||
Matrix(int x, int y) : m_rows(x), m_cols(y), m_array(x*y)
|
||||
Matrix(int x, int y) : m_storage(x*y, x, y)
|
||||
{
|
||||
if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|
||||
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
|
||||
{
|
||||
m_array.data()[0] = x;
|
||||
m_array.data()[1] = y;
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -269,35 +238,35 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
{
|
||||
assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|
||||
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1));
|
||||
m_array.data()[0] = x;
|
||||
m_array.data()[1] = y;
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
}
|
||||
/** constructs an initialized 2D vector with given coefficients */
|
||||
Matrix(const double& x, const double& y)
|
||||
{
|
||||
assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|
||||
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1));
|
||||
m_array.data()[0] = x;
|
||||
m_array.data()[1] = y;
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
}
|
||||
/** constructs an initialized 3D vector with given coefficients */
|
||||
Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
|
||||
{
|
||||
assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 3)
|
||||
|| (RowsAtCompileTime == 3 && ColsAtCompileTime == 1));
|
||||
m_array.data()[0] = x;
|
||||
m_array.data()[1] = y;
|
||||
m_array.data()[2] = z;
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
}
|
||||
/** constructs an initialized 4D vector with given coefficients */
|
||||
Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
|
||||
{
|
||||
assert((RowsAtCompileTime == 1 && ColsAtCompileTime == 4)
|
||||
|| (RowsAtCompileTime == 4 && ColsAtCompileTime == 1));
|
||||
m_array.data()[0] = x;
|
||||
m_array.data()[1] = y;
|
||||
m_array.data()[2] = z;
|
||||
m_array.data()[3] = w;
|
||||
m_storage.data()[0] = x;
|
||||
m_storage.data()[1] = y;
|
||||
m_storage.data()[2] = z;
|
||||
m_storage.data()[3] = w;
|
||||
}
|
||||
Matrix(const Scalar *data, int rows, int cols);
|
||||
Matrix(const Scalar *data, int size);
|
||||
@ -306,17 +275,13 @@ class Matrix : public MatrixBase<_Scalar, Matrix<_Scalar, _Rows, _Cols,
|
||||
/** Constructor copying the value of the expression \a other */
|
||||
template<typename OtherDerived>
|
||||
Matrix(const MatrixBase<Scalar, OtherDerived>& other)
|
||||
: m_rows(other.rows()),
|
||||
m_cols(other.cols()),
|
||||
m_array(other.rows() * other.cols())
|
||||
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
/** Copy constructor */
|
||||
Matrix(const Matrix& other)
|
||||
: m_rows(other.rows()),
|
||||
m_cols(other.cols()),
|
||||
m_array(other.rows() * other.cols())
|
||||
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ template<typename MatrixType> class MatrixRef
|
||||
MaxColsAtCompileTime = MatrixType::Traits::MaxColsAtCompileTime
|
||||
};
|
||||
|
||||
MatrixRef _ref() const { return *this; }
|
||||
int _rows() const { return m_matrix.rows(); }
|
||||
int _cols() const { return m_matrix.cols(); }
|
||||
|
||||
|
184
Eigen/src/Core/MatrixStorage.h
Normal file
184
Eigen/src/Core/MatrixStorage.h
Normal file
@ -0,0 +1,184 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra. Eigen itself is part of the KDE project.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@gmail.com>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Alternatively, you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef EIGEN_MATRIXSTORAGE_H
|
||||
#define EIGEN_MATRIXSTORAGE_H
|
||||
|
||||
|
||||
/** \class MatrixStorage
|
||||
*
|
||||
* \brief Stores the data of a matrix
|
||||
*
|
||||
* \internal
|
||||
*
|
||||
* 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> class MatrixStorage;
|
||||
|
||||
// purely fixed-size matrix.
|
||||
template<typename T, int Size, int _Rows, int _Cols> class MatrixStorage
|
||||
{
|
||||
T m_data[Size];
|
||||
public:
|
||||
MatrixStorage() {}
|
||||
MatrixStorage(int,int,int) {}
|
||||
static int rows(void) {return _Rows;}
|
||||
static int cols(void) {return _Cols;}
|
||||
void resize(int,int,int) {}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage
|
||||
template<typename T, int Size> class MatrixStorage<T, Size, Dynamic, Dynamic>
|
||||
{
|
||||
T m_data[Size];
|
||||
int m_rows;
|
||||
int m_cols;
|
||||
public:
|
||||
MatrixStorage(int, int nbRows, int nbCols) : m_rows(nbRows), m_cols(nbCols) {}
|
||||
~MatrixStorage() {}
|
||||
int rows(void) const {return m_rows;}
|
||||
int cols(void) const {return m_cols;}
|
||||
void resize(int, int nbRows, int nbCols)
|
||||
{
|
||||
m_rows = nbRows;
|
||||
m_cols = nbCols;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage and fixed width
|
||||
template<typename T, int Size, int _Cols> class MatrixStorage<T, Size, Dynamic, _Cols>
|
||||
{
|
||||
T m_data[Size];
|
||||
int m_rows;
|
||||
public:
|
||||
MatrixStorage(int, int nbRows, int) : m_rows(nbRows) {}
|
||||
~MatrixStorage() {}
|
||||
int rows(void) const {return m_rows;}
|
||||
int cols(void) const {return _Cols;}
|
||||
void resize(int size, int nbRows, int)
|
||||
{
|
||||
m_rows = nbRows;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// dynamic-size matrix with fixed-size storage and fixed height
|
||||
template<typename T, int Size, int _Rows> class MatrixStorage<T, Size, _Rows, Dynamic>
|
||||
{
|
||||
T m_data[Size];
|
||||
int m_cols;
|
||||
public:
|
||||
MatrixStorage(int, int nbRows, int nbCols) : m_cols(nbCols) {}
|
||||
~MatrixStorage() {}
|
||||
int rows(void) const {return _Rows;}
|
||||
int cols(void) const {return m_cols;}
|
||||
void resize(int size, int, int nbCols)
|
||||
{
|
||||
m_cols = nbCols;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// purely dynamic matrix.
|
||||
template<typename T> class MatrixStorage<T, Dynamic, Dynamic, Dynamic>
|
||||
{
|
||||
T *m_data;
|
||||
int m_rows;
|
||||
int m_cols;
|
||||
public:
|
||||
MatrixStorage(int size, int nbRows, int nbCols) : m_data(new T[size]), m_rows(nbRows), m_cols(nbCols) {}
|
||||
~MatrixStorage() { delete[] m_data; }
|
||||
int rows(void) const {return m_rows;}
|
||||
int cols(void) const {return m_cols;}
|
||||
void resize(int size, int nbRows, int nbCols)
|
||||
{
|
||||
if(size != m_rows*m_cols)
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = new T[size];
|
||||
}
|
||||
m_rows = nbRows;
|
||||
m_cols = nbCols;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// matrix with dynamic width and fixed height (so that matrix has dynamic size).
|
||||
template<typename T, int _Rows> class MatrixStorage<T, Dynamic, _Rows, Dynamic>
|
||||
{
|
||||
T *m_data;
|
||||
int m_cols;
|
||||
public:
|
||||
MatrixStorage(int size, int, int nbCols) : m_data(new T[size]), m_cols(nbCols) {}
|
||||
~MatrixStorage() { delete[] m_data; }
|
||||
static int rows(void) {return _Rows;}
|
||||
int cols(void) const {return m_cols;}
|
||||
void resize(int size, int, int nbCols)
|
||||
{
|
||||
if(size != _Rows*m_cols)
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = new T[size];
|
||||
}
|
||||
m_cols = nbCols;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
// matrix with dynamic height and fixed width (so that matrix has dynamic size).
|
||||
template<typename T, int _Cols> class MatrixStorage<T, Dynamic, Dynamic, _Cols>
|
||||
{
|
||||
T *m_data;
|
||||
int m_rows;
|
||||
public:
|
||||
MatrixStorage(int size, int nbRows, int) : m_data(new T[size]), m_rows(nbRows) {}
|
||||
~MatrixStorage() { delete[] m_data; }
|
||||
int rows(void) const {return m_rows;}
|
||||
static int cols(void) {return _Cols;}
|
||||
void resize(int size, int nbRows, int)
|
||||
{
|
||||
if(size != m_rows*_Cols)
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = new T[size];
|
||||
}
|
||||
m_rows = nbRows;
|
||||
}
|
||||
const T *data() const { return m_data; }
|
||||
T *data() { return m_data; }
|
||||
};
|
||||
|
||||
#endif // EIGEN_MATRIX_H
|
Loading…
x
Reference in New Issue
Block a user