* remove set(), revert to old behavior where = resizes

* try to be clever in matrix ctors and operator=: be lazy when we can, always allow
  to copy rowvector into columnvector, check the template parameters,
  try to factor the code better
* add missing copy ctor in UnalignedType
* fix bug in the traits of DiagonalProduct
* renaming: EIGEN_TUNE_FOR_CPU_CACHE_SIZE
* update the dox a little
This commit is contained in:
Benoit Jacob
2009-01-21 17:10:23 +00:00
parent a5fbf27843
commit 5f43a42ee7
17 changed files with 170 additions and 114 deletions

View File

@@ -81,7 +81,7 @@ static void ei_cache_friendly_product(
MaxBlockRows_ClampingMask = 0xFFFFF8,
#endif
// maximal size of the blocks fitted in L2 cache
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_L2_CACHE_SIZE,Scalar>::width
MaxL2BlockSize = ei_L2_block_traits<EIGEN_TUNE_FOR_CPU_CACHE_SIZE,Scalar>::width
};
const bool resIsAligned = (PacketSize==1) || (((resStride%PacketSize) == 0) && (size_t(res)%16==0));

View File

@@ -73,7 +73,7 @@ struct ei_traits<Product<LhsNested, RhsNested, DiagonalProduct> >
RemovedBits = ~((RhsFlags & RowMajorBit) && (!CanVectorizeLhs) ? 0 : RowMajorBit),
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
| (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0),
| (((CanVectorizeLhs&&RhsIsDiagonal) || (CanVectorizeRhs&&LhsIsDiagonal)) ? PacketAccessBit : 0),
CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost
};
@@ -114,12 +114,10 @@ template<typename LhsNested, typename RhsNested> class Product<LhsNested, RhsNes
{
if (RhsIsDiagonal)
{
ei_assert((_LhsNested::Flags&RowMajorBit)==0);
return ei_pmul(m_lhs.template packet<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col)));
}
else
{
ei_assert(_RhsNested::Flags&RowMajorBit);
return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packet<LoadMode>(row, col));
}
}

View File

@@ -102,17 +102,13 @@ template<typename MatrixType, int PacketAccess> class Map
* Only for fixed-size matrices and vectors.
* \param data The array of data to copy
*
* For dynamic-size matrices and vectors, see the variants taking additional int parameters
* for the dimensions.
*
* \sa Matrix(const Scalar *, int), Matrix(const Scalar *, int, int),
* Matrix::Map(const Scalar *)
* \sa Matrix::Map(const Scalar *)
*/
template<typename _Scalar, int _Rows, int _Cols, int _StorageOrder, int _MaxRows, int _MaxCols>
inline Matrix<_Scalar, _Rows, _Cols, _StorageOrder, _MaxRows, _MaxCols>
::Matrix(const Scalar *data)
{
*this = Eigen::Map<Matrix>(data);
_set_noalias(Eigen::Map<Matrix>(data));
}
#endif // EIGEN_MAP_H

View File

@@ -226,12 +226,11 @@ class Matrix
*/
inline void resize(int rows, int cols)
{
ei_assert(rows > 0
&& (MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& cols > 0
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
ei_assert(rows > 0 && cols > 0 && "a matrix cannot be resized to 0 size");
ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows)
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
m_storage.resize(rows * cols, rows, cols);
}
@@ -249,49 +248,19 @@ class Matrix
m_storage.resize(size, size, 1);
}
/** Copies the value of the expression \a other into \c *this.
*
* \warning Note that the sizes of \c *this and \a other must match.
* If you want automatic resizing, then you must use the function set().
*
* As a special exception, copying a row-vector into a vector (and conversely)
* is allowed.
*
* \sa set()
*/
template<typename OtherDerived>
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
{
ei_assert(m_storage.data()!=0 && "you cannot use operator= with a non initialized matrix (instead use set()");
return Base::operator=(other.derived());
}
/** Copies the value of the expression \a other into \c *this with automatic resizing.
*
* This function is the same than the assignment operator = excepted that \c *this might
* be resized to match the dimensions of \a other.
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
* it will be initialized.
*
* Note that copying a row-vector into a vector (and conversely) is allowed.
* The resizing, if any, is then done in the appropriate way so that row-vectors
* remain row-vectors and vectors remain vectors.
*
* \sa operator=()
*/
template<typename OtherDerived>
inline Matrix& set(const MatrixBase<OtherDerived>& other)
EIGEN_STRONG_INLINE Matrix& operator=(const MatrixBase<OtherDerived>& other)
{
if(RowsAtCompileTime == 1)
{
ei_assert(other.isVector());
resize(1, other.size());
}
else if(ColsAtCompileTime == 1)
{
ei_assert(other.isVector());
resize(other.size(), 1);
}
else resize(other.rows(), other.cols());
return Base::operator=(other.derived());
return _set(other);
}
/** This is a special case of the templated operator=. Its purpose is to
@@ -299,7 +268,7 @@ class Matrix
*/
EIGEN_STRONG_INLINE Matrix& operator=(const Matrix& other)
{
return operator=<Matrix>(other);
return _set(other);
}
EIGEN_INHERIT_ASSIGNMENT_OPERATOR(Matrix, +=)
@@ -311,34 +280,23 @@ class Matrix
*
* For fixed-size matrices, does nothing.
*
* For dynamic-size matrices, creates an empty matrix of size null.
* \warning while creating such an \em null matrix is allowed, it \b cannot
* \b be \b used before having being resized or initialized with the function set().
* In particular, initializing a null matrix with operator = is not supported.
* Finally, this constructor is the unique way to create null matrices: resizing
* For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix
* is called a null matrix. This constructor is the unique way to create null matrices: resizing
* a matrix to 0 is not supported.
* Here are some examples:
* \code
* MatrixXf r = MatrixXf::Random(3,4); // create a random matrix of floats
* MatrixXf m1, m2; // creates two null matrices of float
*
* m1 = r; // illegal (raise an assertion)
* r = m1; // illegal (raise an assertion)
* m1 = m2; // illegal (raise an assertion)
* m1.set(r); // OK
* m2.resize(3,4);
* m2 = r; // OK
* \endcode
*
* \sa resize(int,int), set()
* \sa resize(int,int)
*/
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
{
ei_assert(RowsAtCompileTime > 0 && ColsAtCompileTime > 0);
_check_template_params();
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
Matrix(ei_constructor_without_unaligned_array_assert)
: m_storage(ei_constructor_without_unaligned_array_assert()) {}
: m_storage(ei_constructor_without_unaligned_array_assert())
{}
#endif
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
*
@@ -349,6 +307,7 @@ class Matrix
EIGEN_STRONG_INLINE explicit Matrix(int dim)
: m_storage(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
ei_assert(dim > 0);
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
@@ -366,6 +325,7 @@ class Matrix
*/
EIGEN_STRONG_INLINE Matrix(int x, int y) : m_storage(x*y, x, y)
{
_check_template_params();
if((RowsAtCompileTime == 1 && ColsAtCompileTime == 2)
|| (RowsAtCompileTime == 2 && ColsAtCompileTime == 1))
{
@@ -381,6 +341,7 @@ class Matrix
/** constructs an initialized 2D vector with given coefficients */
EIGEN_STRONG_INLINE Matrix(const float& x, const float& y)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
m_storage.data()[0] = x;
m_storage.data()[1] = y;
@@ -388,6 +349,7 @@ class Matrix
/** constructs an initialized 2D vector with given coefficients */
EIGEN_STRONG_INLINE Matrix(const double& x, const double& y)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 2)
m_storage.data()[0] = x;
m_storage.data()[1] = y;
@@ -395,6 +357,7 @@ class Matrix
/** constructs an initialized 3D vector with given coefficients */
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
m_storage.data()[0] = x;
m_storage.data()[1] = y;
@@ -403,6 +366,7 @@ class Matrix
/** constructs an initialized 4D vector with given coefficients */
EIGEN_STRONG_INLINE Matrix(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w)
{
_check_template_params();
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 4)
m_storage.data()[0] = x;
m_storage.data()[1] = y;
@@ -417,14 +381,15 @@ class Matrix
EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
{
ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
//Base::operator=(other.derived());
_check_template_params();
_set_noalias(other);
}
/** Copy constructor */
EIGEN_STRONG_INLINE Matrix(const Matrix& other)
: Base(), m_storage(other.rows() * other.cols(), other.rows(), other.cols())
{
Base::lazyAssign(other);
_check_template_params();
_set_noalias(other);
}
/** Destructor */
inline ~Matrix() {}
@@ -486,6 +451,72 @@ class Matrix
#ifdef EIGEN_MATRIX_PLUGIN
#include EIGEN_MATRIX_PLUGIN
#endif
private:
/** \internal Resizes *this in preparation for assigning \a other to it.
* Takes care of doing all the checking that's needed.
*
* Note that copying a row-vector into a vector (and conversely) is allowed.
* The resizing, if any, is then done in the appropriate way so that row-vectors
* remain row-vectors and vectors remain vectors.
*/
template<typename OtherDerived>
EIGEN_STRONG_INLINE void _resize_to_match(const MatrixBase<OtherDerived>& other)
{
if(RowsAtCompileTime == 1)
{
ei_assert(other.isVector());
resize(1, other.size());
}
else if(ColsAtCompileTime == 1)
{
ei_assert(other.isVector());
resize(other.size(), 1);
}
else resize(other.rows(), other.cols());
}
/** \internal Copies the value of the expression \a other into \c *this with automatic resizing.
*
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
* it will be initialized.
*
* Note that copying a row-vector into a vector (and conversely) is allowed.
* The resizing, if any, is then done in the appropriate way so that row-vectors
* remain row-vectors and vectors remain vectors.
*
* \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias()
*/
template<typename OtherDerived>
EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
{
_resize_to_match(other);
return Base::operator=(other);
}
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
* is the case when creating a new matrix) so one can enforce lazy evaluation.
*
* \sa operator=(const MatrixBase<OtherDerived>&), _set()
*/
template<typename OtherDerived>
EIGEN_STRONG_INLINE Matrix& _set_noalias(const MatrixBase<OtherDerived>& other)
{
_resize_to_match(other);
// the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
// it wouldn't allow to copy a row-vector into a column-vector.
return ei_assign_selector<Matrix,OtherDerived,false>::run(*this, other.derived());
}
static EIGEN_STRONG_INLINE void _check_template_params()
{
EIGEN_STATIC_ASSERT((_Rows > 0
&& _Cols > 0
&& _MaxRows <= _Rows
&& _MaxCols <= _Cols
&& (_Options & (AutoAlign|RowMajor)) == _Options),
INVALID_MATRIX_TEMPLATE_PARAMETERS)
}
};
/** \defgroup matrixtypedefs Global matrix typedefs

View File

@@ -175,7 +175,7 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
if (m.rows()==m.cols())
m.template part<StrictlyUpperTriangular>().swap(m.transpose());
else
m.set(m.transpose().eval());
m = m.transpose().eval();
}
};
@@ -186,7 +186,7 @@ struct ei_inplace_transpose_selector<MatrixType,false> { // non square matrix
* then this "in-place" version is probably the right choice because it provides
* the following additional features:
* - less error prone: doing the same operation with .transpose() requires special care:
* \code m.set(m.transpose().eval()); \endcode
* \code m = m.transpose().eval(); \endcode
* - no temporary object is created (currently only for squared matrices)
* - it allows future optimizations (cache friendliness, etc.)
*

View File

@@ -50,10 +50,18 @@
#define EIGEN_UNROLLING_LIMIT 100
#endif
/** \internal Define the maximal size in Bytes of L2 blocks.
* The current value is set to generate blocks of 256x256 for float */
#ifndef EIGEN_TUNE_FOR_L2_CACHE_SIZE
#define EIGEN_TUNE_FOR_L2_CACHE_SIZE (sizeof(float)*256*256)
/** \internal Define the maximal size in Bytes of blocks fitting in CPU cache.
* The current value is set to generate blocks of 256x256 for float
*
* Typically for a single-threaded application you would set that to 25% of the size of your CPU caches in bytes
*/
#ifndef EIGEN_TUNE_FOR_CPU_CACHE_SIZE
#define EIGEN_TUNE_FOR_CPU_CACHE_SIZE (sizeof(float)*256*256)
#endif
// FIXME this should go away quickly
#ifdef EIGEN_TUNE_FOR_L2_CACHE_SIZE
#error EIGEN_TUNE_FOR_L2_CACHE_SIZE is now called EIGEN_TUNE_FOR_CPU_CACHE_SIZE.
#endif
#define USING_PART_OF_NAMESPACE_EIGEN \

View File

@@ -115,11 +115,11 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
#endif
void *void_result = malloc(size);
void *result = malloc(size);
#ifdef EIGEN_EXCEPTIONS
if(!void_result) throw std::bad_alloc();
if(!result) throw std::bad_alloc();
#endif
return void_result;
return result;
}
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.

View File

@@ -71,7 +71,8 @@
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS,
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION,
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY,
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
INVALID_MATRIX_TEMPLATE_PARAMETERS
};
};

View File

@@ -32,13 +32,24 @@ template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int
class ei_unaligned_type<Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> >
: public Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols>
{
private:
template<typename Other> void _unaligned_copy(const Other& other)
{
if(other.size() == 0) return;
resize(other.rows(), other.cols());
ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
}
public:
typedef Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> aligned_base;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
resize(other.rows(), other.cols());
ei_assign_impl<ei_unaligned_type,aligned_base,NoVectorization>::run(*this, other);
_unaligned_copy(other);
}
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
_unaligned_copy(other);
}
};
@@ -46,14 +57,23 @@ template<typename _Scalar, int _Dim>
class ei_unaligned_type<Transform<_Scalar,_Dim> >
: public Transform<_Scalar,_Dim>
{
private:
template<typename Other> void _unaligned_copy(const Other& other)
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<MatrixType,MatrixType,NoVectorization>::run(this->matrix(), other.matrix());
}
public:
typedef Transform<_Scalar,_Dim> aligned_base;
typedef typename aligned_base::MatrixType MatrixType;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<MatrixType,MatrixType,NoVectorization>::run(this->matrix(), other.matrix());
_unaligned_copy(other);
}
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
_unaligned_copy(other);
}
};
@@ -61,14 +81,23 @@ template<typename _Scalar>
class ei_unaligned_type<Quaternion<_Scalar> >
: public Quaternion<_Scalar>
{
private:
template<typename Other> void _unaligned_copy(const Other& other)
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<Coefficients,Coefficients,NoVectorization>::run(this->coeffs(), other.coeffs());
}
public:
typedef Quaternion<_Scalar> aligned_base;
typedef typename aligned_base::Coefficients Coefficients;
ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {}
ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
// no resizing here, it's fixed-size anyway
ei_assign_impl<Coefficients,Coefficients,NoVectorization>::run(this->coeffs(), other.coeffs());
_unaligned_copy(other);
}
ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert())
{
_unaligned_copy(other);
}
};