- rework the coefficients API

- make vectors use a separate loop unroller, so that copying a
row-vector into a col-vector is now possible
- add much more documentation
- misc improvements
This commit is contained in:
Benoit Jacob
2007-12-24 11:14:25 +00:00
parent e937583655
commit 3cd2a125b2
24 changed files with 485 additions and 111 deletions

View File

@@ -26,6 +26,28 @@
#ifndef EIGEN_BLOCK_H
#define EIGEN_BLOCK_H
/** \class Block
*
* \brief Expression of a fixed-size block
*
* \param MatrixType the type of the object in which we are taking a block
* \param BlockRows the number of rows of the block we are taking
* \param BlockCols the number of columns of the block we are taking
*
* This class represents an expression of a fixed-size block. It is the return
* type of MatrixBase::block() and most of the time this is the only way it
* is used.
*
* However, if you want to directly maniputate fixed-size block expressions,
* for instance if you want to write a function returning such an expression, you
* will need to use this class.
*
* Here is an example illustrating this:
* \include class_Block.cpp
* Output: \verbinclude class_Block.out
*
* \sa MatrixBase::block(), class DynBlock
*/
template<typename MatrixType, int BlockRows, int BlockCols> class Block
: public MatrixBase<typename MatrixType::Scalar,
Block<MatrixType, BlockRows, BlockCols> >
@@ -71,6 +93,18 @@ template<typename MatrixType, int BlockRows, int BlockCols> class Block
const int m_startRow, m_startCol;
};
/** \returns a fixed-size expression of a block in *this.
*
* \param blockRows the number of rows in the block
* \param blockCols the number of columns in the block
* \param startRow the first row in the block
* \param startCol the first column in the block
*
* Example: \include MatrixBase_block.cpp
* Output: \verbinclude MatrixBase_block.out
*
* \sa class Block, dynBlock()
*/
template<typename Scalar, typename Derived>
template<int BlockRows, int BlockCols>
Block<Derived, BlockRows, BlockCols> MatrixBase<Scalar, Derived>

View File

@@ -26,6 +26,26 @@
#ifndef EIGEN_CAST_H
#define EIGEN_CAST_H
/** \class Cast
*
* \brief Expression with casted scalar type
*
* \param NewScalar the new scalar type
* \param MatrixType the type of the object in which we are casting the scalar type
*
* This class represents an expression where we are casting the scalar type to a new
* type. It is the return type of MatrixBase::cast() and most of the time this is the
* only way it is used.
*
* However, if you want to write a function returning such an expression, you
* will need to use this class.
*
* Here is an example illustrating this:
* \include class_Cast.cpp
* Output: \verbinclude class_Cast.out
*
* \sa MatrixBase::cast()
*/
template<typename NewScalar, typename MatrixType> class Cast : NoOperatorEquals,
public MatrixBase<NewScalar, Cast<NewScalar, MatrixType> >
{
@@ -56,7 +76,15 @@ template<typename NewScalar, typename MatrixType> class Cast : NoOperatorEquals,
};
/** \returns an expression of *this with the \a Scalar type casted to
* \a NewScalar. */
* \a NewScalar.
*
* \param NewScalar the type we are casting the scalars to
*
* Example: \include MatrixBase_cast.cpp
* Output: \verbinclude MatrixBase_cast.out
*
* \sa class Cast
*/
template<typename Scalar, typename Derived>
template<typename NewScalar>
const Cast<NewScalar, Derived>

View File

@@ -26,105 +26,225 @@
#ifndef EIGEN_COEFFS_H
#define EIGEN_COEFFS_H
/** Short version: don't use this function, use
* \link operator()(int,int) const \endlink instead.
*
* Long version: this function is similar to
* \link operator()(int,int) const \endlink, but without the assertion.
* Use this for limiting the performance cost of debugging code when doing
* repeated coefficient access. Only use this when it is guaranteed that the
* parameters \a row and \a col are in range.
*
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
* function equivalent to \link operator()(int,int) const \endlink.
*
* \sa operator()(int,int) const, coeffRef(int,int), coeff(int) const
*/
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::coeff(int row, int col, AssertLevel assertLevel = InternalDebugging) const
::coeff(int row, int col) const
{
eigen_assert(assertLevel, row >= 0 && row < rows()
&& col >= 0 && col < cols());
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return static_cast<const Derived *>(this)->_coeff(row, col);
}
/** \returns the coefficient at given the given row and column.
*
* \sa operator()(int,int), operator[](int) const
*/
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::operator()(int row, int col) const { return coeff(row, col, UserDebugging); }
::operator()(int row, int col) const
{
assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return static_cast<const Derived *>(this)->_coeff(row, col);
}
/** Short version: don't use this function, use
* \link operator()(int,int) \endlink instead.
*
* Long version: this function is similar to
* \link operator()(int,int) \endlink, but without the assertion.
* Use this for limiting the performance cost of debugging code when doing
* repeated coefficient access. Only use this when it is guaranteed that the
* parameters \a row and \a col are in range.
*
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
* function equivalent to \link operator()(int,int) \endlink.
*
* \sa operator()(int,int), coeff(int, int) const, coeffRef(int)
*/
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::coeffRef(int row, int col, AssertLevel assertLevel = InternalDebugging)
::coeffRef(int row, int col)
{
eigen_assert(assertLevel, row >= 0 && row < rows()
&& col >= 0 && col < cols());
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return static_cast<Derived *>(this)->_coeffRef(row, col);
}
/** \returns a reference to the coefficient at given the given row and column.
*
* \sa operator()(int,int) const, operator[](int)
*/
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::operator()(int row, int col) { return coeffRef(row, col, UserDebugging); }
::operator()(int row, int col)
{
assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return static_cast<Derived *>(this)->_coeffRef(row, col);
}
/** Short version: don't use this function, use
* \link operator[](int) const \endlink instead.
*
* Long version: this function is similar to
* \link operator[](int) const \endlink, but without the assertion.
* Use this for limiting the performance cost of debugging code when doing
* repeated coefficient access. Only use this when it is guaranteed that the
* parameters \a row and \a col are in range.
*
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
* function equivalent to \link operator[](int) const \endlink.
*
* \sa operator[](int) const, coeffRef(int), coeff(int,int) const
*/
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::coeff(int index, AssertLevel assertLevel = InternalDebugging) const
::coeff(int index) const
{
eigen_assert(assertLevel, IsVector);
eigen_internal_assert(IsVector);
if(RowsAtCompileTime == 1)
{
eigen_assert(assertLevel, index >= 0 && index < cols());
eigen_internal_assert(index >= 0 && index < cols());
return coeff(0, index);
}
else
{
eigen_assert(assertLevel, index >= 0 && index < rows());
eigen_internal_assert(index >= 0 && index < rows());
return coeff(index, 0);
}
}
/** \returns the coefficient at given index.
*
* \only_for_vectors
*
* \sa operator[](int), operator()(int,int) const, x() const, y() const,
* z() const, w() const
*/
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::operator[](int index) const { return coeff(index, UserDebugging); }
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::coeffRef(int index, AssertLevel assertLevel = InternalDebugging)
::operator[](int index) const
{
eigen_assert(assertLevel, IsVector);
assert(IsVector);
if(RowsAtCompileTime == 1)
{
eigen_assert(assertLevel, index >= 0 && index < cols());
assert(index >= 0 && index < cols());
return coeff(0, index);
}
else
{
assert(index >= 0 && index < rows());
return coeff(index, 0);
}
}
/** Short version: don't use this function, use
* \link operator[](int) \endlink instead.
*
* Long version: this function is similar to
* \link operator[](int) \endlink, but without the assertion.
* Use this for limiting the performance cost of debugging code when doing
* repeated coefficient access. Only use this when it is guaranteed that the
* parameters \a row and \a col are in range.
*
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this
* function equivalent to \link operator[](int) \endlink.
*
* \sa operator[](int), coeff(int) const, coeffRef(int,int)
*/
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::coeffRef(int index)
{
eigen_internal_assert(IsVector);
if(RowsAtCompileTime == 1)
{
eigen_internal_assert(index >= 0 && index < cols());
return coeffRef(0, index);
}
else
{
eigen_assert(assertLevel, index >= 0 && index < rows());
eigen_internal_assert(index >= 0 && index < rows());
return coeffRef(index, 0);
}
}
/** \returns a reference to the coefficient at given index.
*
* \only_for_vectors
*
* \sa operator[](int) const, operator()(int,int), x(), y(), z(), w()
*/
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::operator[](int index) { return coeffRef(index, UserDebugging); }
::operator[](int index)
{
assert(IsVector);
if(RowsAtCompileTime == 1)
{
assert(index >= 0 && index < cols());
return coeffRef(0, index);
}
else
{
assert(index >= 0 && index < rows());
return coeffRef(index, 0);
}
}
/** equivalent to operator[](0). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::x() const { return coeff(0, UserDebugging); }
::x() const { return (*this)[0]; }
/** equivalent to operator[](1). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::y() const { return coeff(1, UserDebugging); }
::y() const { return (*this)[1]; }
/** equivalent to operator[](2). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::z() const { return coeff(2, UserDebugging); }
::z() const { return (*this)[2]; }
/** equivalent to operator[](3). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar MatrixBase<Scalar, Derived>
::w() const { return coeff(3, UserDebugging); }
::w() const { return (*this)[3]; }
/** equivalent to operator[](0). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::x() { return coeffRef(0, UserDebugging); }
::x() { return (*this)[0]; }
/** equivalent to operator[](1). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::y() { return coeffRef(1, UserDebugging); }
::y() { return (*this)[1]; }
/** equivalent to operator[](2). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::z() { return coeffRef(2, UserDebugging); }
::z() { return (*this)[2]; }
/** equivalent to operator[](3). \only_for_vectors */
template<typename Scalar, typename Derived>
Scalar& MatrixBase<Scalar, Derived>
::w() { return coeffRef(3, UserDebugging); }
::w() { return (*this)[3]; }
#endif // EIGEN_COEFFS_H

View File

@@ -26,6 +26,26 @@
#ifndef EIGEN_COLUMN_H
#define EIGEN_COLUMN_H
/** \class Column
*
* \brief Expression of a column
*
* \param MatrixType the type of the object in which we are taking a column
*
* This class represents an expression of a column. It is the return
* type of MatrixBase::col() and most of the time this is the only way it
* is used.
*
* However, if you want to directly maniputate column expressions,
* for instance if you want to write a function returning such an expression, you
* will need to use this class.
*
* Here is an example illustrating this:
* \include class_Column.cpp
* Output: \verbinclude class_Column.out
*
* \sa MatrixBase::col()
*/
template<typename MatrixType> class Column
: public MatrixBase<typename MatrixType::Scalar, Column<MatrixType> >
{
@@ -67,8 +87,12 @@ template<typename MatrixType> class Column
const int m_col;
};
/** \returns an expression of the \a i-th column of *this.
* \sa row(int) */
/** \returns an expression of the \a i-th column of *this. Note that the numbering starts at 0.
*
* Example: \include MatrixBase_col.cpp
* Output: \verbinclude MatrixBase_col.out
*
* \sa row(), class Column */
template<typename Scalar, typename Derived>
Column<Derived>
MatrixBase<Scalar, Derived>::col(int i) const

View File

@@ -30,9 +30,11 @@
*
* \brief Expression of a dynamic-size block
*
* \param MatrixType the type of the object in which we are taking a block
*
* This class represents an expression of a dynamic-size block. It is the return
* type of MatrixBase::dynBlock() and most of the time this is the only way this
* class is used.
* type of MatrixBase::dynBlock() and most of the time this is the only way it
* is used.
*
* However, if you want to directly maniputate dynamic-size block expressions,
* for instance if you want to write a function returning such an expression, you
@@ -40,8 +42,7 @@
*
* Here is an example illustrating this:
* \include class_DynBlock.cpp
* Output:
* \verbinclude class_DynBlock.out
* Output: \verbinclude class_DynBlock.out
*
* \sa MatrixBase::dynBlock()
*/
@@ -101,12 +102,10 @@ template<typename MatrixType> class DynBlock
* \param blockRows the number of rows in the block
* \param blockCols the number of columns in the block
*
* Example:
* \include MatrixBase_dynBlock.cpp
* Output:
* \verbinclude MatrixBase_dynBlock.out
* Example: \include MatrixBase_dynBlock.cpp
* Output: \verbinclude MatrixBase_dynBlock.out
*
* \sa class DynBlock
* \sa class DynBlock, block()
*/
template<typename Scalar, typename Derived>
DynBlock<Derived> MatrixBase<Scalar, Derived>

View File

@@ -55,12 +55,17 @@
template<typename Scalar, typename Derived> class MatrixBase
{
public:
/** The number of rows and of columns at compile-time. These are just
* copies of the values provided by the \a Derived type. If a value
* is not known at compile-time, it is set to the \a Dynamic constant.
* \sa rows(), cols(), SizeAtCompileTime */
static const int RowsAtCompileTime = Derived::_RowsAtCompileTime,
ColsAtCompileTime = Derived::_ColsAtCompileTime;
/** The number of rows at compile-time. This is just a copy of the value provided
* by the \a Derived type. If a value is not known at compile-time,
* it is set to the \a Dynamic constant.
* \sa rows(), cols(), ColsAtCompileTime, SizeAtCompileTime */
static const int RowsAtCompileTime = Derived::_RowsAtCompileTime;
/** The number of columns at compile-time. This is just a copy of the value provided
* by the \a Derived type. If a value is not known at compile-time,
* it is set to the \a Dynamic constant.
* \sa rows(), cols(), RowsAtCompileTime, SizeAtCompileTime */
static const int ColsAtCompileTime = Derived::_ColsAtCompileTime;
/** This is equal to the number of coefficients, i.e. the number of
* rows times the number of columns, or to \a Dynamic if this is not
@@ -77,9 +82,9 @@ template<typename Scalar, typename Derived> class MatrixBase
/** This is the "reference type" used to pass objects of type MatrixBase as arguments
* to functions. If this MatrixBase type represents an expression, then \a Ref
* is just this MatrixBase type itself, i.e. expressions are just passed by value
* and the compiler is supposed to be clever enough to optimize that. If, on the
* other hand, this MatrixBase type is an actual matrix or vector, then \a Ref is
* a typedef MatrixRef, which is like a reference, so that matrices and vectors
* and the compiler is usually clever enough to optimize that. If, on the
* other hand, this MatrixBase type is an actual matrix or vector type, then \a Ref is
* a typedef to MatrixRef, which works as a reference, so that matrices and vectors
* are passed by reference, not by value. \sa ref()*/
typedef typename ForwardDecl<Derived>::Ref Ref;
@@ -195,16 +200,16 @@ template<typename Scalar, typename Derived> class MatrixBase
Derived& operator/=(const std::complex<float>& other);
Derived& operator/=(const std::complex<double>& other);
Scalar coeff(int row, int col, AssertLevel assertLevel) const;
Scalar coeff(int row, int col) const;
Scalar operator()(int row, int col) const;
Scalar& coeffRef(int row, int col, AssertLevel assertLevel);
Scalar& coeffRef(int row, int col);
Scalar& operator()(int row, int col);
Scalar coeff(int index, AssertLevel assertLevel) const;
Scalar coeff(int index) const;
Scalar operator[](int index) const;
Scalar& coeffRef(int index, AssertLevel assertLevel);
Scalar& coeffRef(int index);
Scalar& operator[](int index);
Scalar x() const;

View File

@@ -28,27 +28,27 @@
#define EIGEN_OPERATOREQUALS_H
template<typename Derived1, typename Derived2, int UnrollCount, int Rows>
struct OperatorEqualsUnroller
struct MatrixOperatorEqualsUnroller
{
static const int col = (UnrollCount-1) / Rows;
static const int row = (UnrollCount-1) % Rows;
static void run(Derived1 &dst, const Derived2 &src)
{
OperatorEqualsUnroller<Derived1, Derived2, UnrollCount-1, Rows>::run(dst, src);
MatrixOperatorEqualsUnroller<Derived1, Derived2, UnrollCount-1, Rows>::run(dst, src);
dst.coeffRef(row, col) = src.coeff(row, col);
}
};
// prevent buggy user code from causing an infinite recursion
template<typename Derived1, typename Derived2, int UnrollCount>
struct OperatorEqualsUnroller<Derived1, Derived2, UnrollCount, 0>
struct MatrixOperatorEqualsUnroller<Derived1, Derived2, UnrollCount, 0>
{
static void run(Derived1 &, const Derived2 &) {}
};
template<typename Derived1, typename Derived2, int Rows>
struct OperatorEqualsUnroller<Derived1, Derived2, 1, Rows>
struct MatrixOperatorEqualsUnroller<Derived1, Derived2, 1, Rows>
{
static void run(Derived1 &dst, const Derived2 &src)
{
@@ -57,7 +57,41 @@ struct OperatorEqualsUnroller<Derived1, Derived2, 1, Rows>
};
template<typename Derived1, typename Derived2, int Rows>
struct OperatorEqualsUnroller<Derived1, Derived2, Dynamic, Rows>
struct MatrixOperatorEqualsUnroller<Derived1, Derived2, Dynamic, Rows>
{
static void run(Derived1 &, const Derived2 &) {}
};
template<typename Derived1, typename Derived2, int UnrollCount>
struct VectorOperatorEqualsUnroller
{
static const int index = UnrollCount - 1;
static void run(Derived1 &dst, const Derived2 &src)
{
VectorOperatorEqualsUnroller<Derived1, Derived2, UnrollCount-1>::run(dst, src);
dst.coeffRef(index) = src.coeff(index);
}
};
// prevent buggy user code from causing an infinite recursion
template<typename Derived1, typename Derived2>
struct VectorOperatorEqualsUnroller<Derived1, Derived2, 0>
{
static void run(Derived1 &, const Derived2 &) {}
};
template<typename Derived1, typename Derived2>
struct VectorOperatorEqualsUnroller<Derived1, Derived2, 1>
{
static void run(Derived1 &dst, const Derived2 &src)
{
dst.coeffRef(0) = src.coeff(0);
}
};
template<typename Derived1, typename Derived2>
struct VectorOperatorEqualsUnroller<Derived1, Derived2, Dynamic>
{
static void run(Derived1 &, const Derived2 &) {}
};
@@ -67,16 +101,31 @@ template<typename OtherDerived>
Derived& MatrixBase<Scalar, Derived>
::operator=(const MatrixBase<Scalar, OtherDerived>& other)
{
assert(rows() == other.rows() && cols() == other.cols());
if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 25)
OperatorEqualsUnroller
<Derived, OtherDerived, SizeAtCompileTime, RowsAtCompileTime>::run
(*static_cast<Derived*>(this), *static_cast<const OtherDerived*>(&other));
else
for(int j = 0; j < cols(); j++) //traverse in column-dominant order
for(int i = 0; i < rows(); i++)
coeffRef(i, j) = other.coeff(i, j);
return *static_cast<Derived*>(this);
if(IsVector && OtherDerived::IsVector) // copying a vector expression into a vector
{
assert(size() == other.size());
if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 25)
VectorOperatorEqualsUnroller
<Derived, OtherDerived, SizeAtCompileTime>::run
(*static_cast<Derived*>(this), *static_cast<const OtherDerived*>(&other));
else
for(int i = 0; i < size(); i++)
coeffRef(i) = other.coeff(i);
return *static_cast<Derived*>(this);
}
else // all other cases (typically, but not necessarily, copying a matrix)
{
assert(rows() == other.rows() && cols() == other.cols());
if(EIGEN_UNROLLED_LOOPS && SizeAtCompileTime != Dynamic && SizeAtCompileTime <= 25)
MatrixOperatorEqualsUnroller
<Derived, OtherDerived, SizeAtCompileTime, RowsAtCompileTime>::run
(*static_cast<Derived*>(this), *static_cast<const OtherDerived*>(&other));
else
for(int j = 0; j < cols(); j++) //traverse in column-dominant order
for(int i = 0; i < rows(); i++)
coeffRef(i, j) = other.coeff(i, j);
return *static_cast<Derived*>(this);
}
}
#endif // EIGEN_OPERATOREQUALS_H

View File

@@ -26,6 +26,26 @@
#ifndef EIGEN_ROW_H
#define EIGEN_ROW_H
/** \class Row
*
* \brief Expression of a row
*
* \param MatrixType the type of the object in which we are taking a row
*
* This class represents an expression of a row. It is the return
* type of MatrixBase::row() and most of the time this is the only way it
* is used.
*
* However, if you want to directly maniputate row expressions,
* for instance if you want to write a function returning such an expression, you
* will need to use this class.
*
* Here is an example illustrating this:
* \include class_Row.cpp
* Output: \verbinclude class_Row.out
*
* \sa MatrixBase::row()
*/
template<typename MatrixType> class Row
: public MatrixBase<typename MatrixType::Scalar, Row<MatrixType> >
{
@@ -75,8 +95,12 @@ template<typename MatrixType> class Row
const int m_row;
};
/** \returns an expression of the \a i-th row of *this.
* \sa col(int)*/
/** \returns an expression of the \a i-th row of *this. Note that the numbering starts at 0.
*
* Example: \include MatrixBase_row.cpp
* Output: \verbinclude MatrixBase_row.out
*
* \sa col(), class Row */
template<typename Scalar, typename Derived>
Row<Derived>
MatrixBase<Scalar, Derived>::row(int i) const

View File

@@ -34,18 +34,17 @@
#undef minor
#define USING_EIGEN_DATA_TYPES \
#define USING_PART_OF_NAMESPACE_EIGEN \
EIGEN_USING_MATRIX_TYPEDEFS \
using Eigen::Matrix;
using Eigen::Matrix; \
using Eigen::MatrixBase;
#ifdef EIGEN_INTERNAL_DEBUGGING
#define EIGEN_ASSERT_LEVEL 2
#define eigen_internal_assert(x) assert(x);
#else
#define EIGEN_ASSERT_LEVEL 1
#define eigen_internal_assert(x)
#endif
#define eigen_assert(assertLevel, x) if(assertLevel <= EIGEN_ASSERT_LEVEL) assert(x);
#ifdef NDEBUG
#define EIGEN_ONLY_USED_FOR_DEBUG(x) (void)x
#else
@@ -121,12 +120,6 @@ struct ForwardDecl<Matrix<_Scalar, _Rows, _Cols> >
const int Dynamic = -1;
enum AssertLevel
{
UserDebugging = 1,
InternalDebugging = 2
};
//classes inheriting NoOperatorEquals don't generate a default operator=.
class NoOperatorEquals
{