Make use of the LazyBit, introduce .lazy(), remove lazyProduct.

This commit is contained in:
Benoit Jacob 2008-03-31 16:20:06 +00:00
parent f279162ec4
commit cff5e3ce9c
20 changed files with 79 additions and 81 deletions

View File

@ -21,6 +21,7 @@ namespace Eigen {
#include "src/Core/MatrixStorage.h"
#include "src/Core/Matrix.h"
#include "src/Core/Eval.h"
#include "src/Core/Lazy.h"
#include "src/Core/CwiseBinaryOp.h"
#include "src/Core/CwiseUnaryOp.h"
#include "src/Core/Product.h"

View File

@ -69,7 +69,7 @@ struct ei_traits<Block<MatrixType, BlockRows, BlockCols> >
: (BlockCols==Dynamic ? MatrixType::MaxColsAtCompileTime : BlockCols),
Flags = RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic
? (unsigned int)MatrixType::Flags
: (unsigned int)MatrixType::Flags &~ Large
: (unsigned int)MatrixType::Flags &~ LargeBit
};
};

View File

@ -54,7 +54,7 @@ struct ei_traits<DiagonalCoeffs<MatrixType> >
MaxColsAtCompileTime = 1,
Flags = RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic
? (unsigned int)MatrixType::Flags
: (unsigned int)MatrixType::Flags &~ Large
: (unsigned int)MatrixType::Flags &~ LargeBit
};
};

View File

@ -53,7 +53,7 @@ struct ei_traits<Eval<ExpressionType> >
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
Flags = ExpressionType::Flags & ~Lazy
Flags = ExpressionType::Flags & ~LazyBit
};
};
@ -101,9 +101,9 @@ template<typename ExpressionType> class Eval : ei_no_assignment_operator,
*
* \sa class Eval */
template<typename Derived>
const Eval<Derived> MatrixBase<Derived>::eval() const
const typename ei_eval_unless_lazy<Derived>::Type MatrixBase<Derived>::eval() const
{
return Eval<Derived>(*static_cast<const Derived*>(this));
return typename ei_eval_unless_lazy<Derived>::Type(derived());
}
#endif // EIGEN_EVAL_H

View File

@ -48,7 +48,7 @@ struct ei_traits<EvalOMP<ExpressionType> >
ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
Flags = ExpressionType::Flags & ~Lazy
Flags = ExpressionType::Flags & ~LazyBit
};
};

View File

@ -29,7 +29,7 @@ template<typename T> struct ei_traits;
template<typename Lhs, typename Rhs> struct ei_product_eval_mode;
template<typename _Scalar, int _Rows, int _Cols, unsigned int _Flags, int _MaxRows, int _MaxCols> class Matrix;
template<typename MatrixType> class MatrixRef;
template<typename ExpressionType> class Lazy;
template<typename MatrixType> class Minor;
template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic> class Block;
template<typename MatrixType> class Transpose;
@ -79,4 +79,18 @@ struct ei_xpr_copy<Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> >
typedef const Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> & Type;
};
template<typename T, bool value> struct ei_conditional_eval
{
typedef T Type;
};
template<typename T> struct ei_conditional_eval<T, true>
{
typedef Eval<T> Type;
};
template<typename T> struct ei_eval_unless_lazy
{
typedef typename ei_conditional_eval<T, !(ei_traits<T>::Flags & LazyBit)>::Type Type;
};
#endif // EIGEN_FORWARDDECLARATIONS_H

View File

@ -65,7 +65,7 @@ template<typename MatrixType> class Map
const Scalar& _coeff(int row, int col) const
{
if(Flags & RowMajor)
if(Flags & RowMajorBit)
return m_data[col + row * m_cols];
else // column-major
return m_data[row + col * m_rows];
@ -73,7 +73,7 @@ template<typename MatrixType> class Map
Scalar& _coeffRef(int row, int col)
{
if(Flags & RowMajor)
if(Flags & RowMajorBit)
return const_cast<Scalar*>(m_data)[col + row * m_cols];
else // column-major
return const_cast<Scalar*>(m_data)[row + col * m_rows];

View File

@ -104,7 +104,7 @@ class Matrix : public MatrixBase<Matrix<_Scalar, _Rows, _Cols,
const Scalar& _coeff(int row, int col) const
{
if(Flags & RowMajor)
if(Flags & RowMajorBit)
return m_storage.data()[col + row * m_storage.cols()];
else // column-major
return m_storage.data()[row + col * m_storage.rows()];
@ -112,7 +112,7 @@ class Matrix : public MatrixBase<Matrix<_Scalar, _Rows, _Cols,
Scalar& _coeffRef(int row, int col)
{
if(Flags & RowMajor)
if(Flags & RowMajorBit)
return m_storage.data()[col + row * m_storage.cols()];
else // column-major
return m_storage.data()[row + col * m_storage.rows()];

View File

@ -129,11 +129,11 @@ template<typename Derived> class MatrixBase
Flags = ei_traits<Derived>::Flags
/**< This stores expression metadata which typically is inherited by new expressions
* constructed from this one. The available flags are:
* \li \c RowMajor: if this bit is set, the preferred storage order for an evaluation
* \li \c RowMajorBit: if this bit is set, the preferred storage order for an evaluation
* of this expression is row-major. Otherwise, it is column-major.
* \li \c Lazy: if this bit is set, the next evaluation of this expression will be canceled.
* \li \c LazyBit: if this bit is set, the next evaluation of this expression will be canceled.
* This can be used, with care, to achieve lazy evaluation.
* \li \c Large: if this bit is set, optimization will be tuned for large matrices (typically,
* \li \c LargeBit: if this bit is set, optimization will be tuned for large matrices (typically,
* at least 32x32).
*/
};
@ -246,14 +246,11 @@ template<typename Derived> class MatrixBase
//@}
/** \name Matrix product
* and, as a special case, matrix-vector product
*/
//@{
template<typename OtherDerived>
const Product<Derived, OtherDerived>
lazyProduct(const MatrixBase<OtherDerived>& other) const;
template<typename OtherDerived>
const Eval<Product<Derived, OtherDerived> >
const typename ei_eval_unless_lazy<Product<Derived, OtherDerived> >::Type
operator*(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
@ -313,9 +310,9 @@ template<typename Derived> class MatrixBase
/// \name Generating special matrices
//@{
static const Eval<Random<Derived> > random(int rows, int cols);
static const Eval<Random<Derived> > random(int size);
static const Eval<Random<Derived> > random();
static const typename ei_eval_unless_lazy<Random<Derived> >::Type random(int rows, int cols);
static const typename ei_eval_unless_lazy<Random<Derived> >::Type random(int size);
static const typename ei_eval_unless_lazy<Random<Derived> >::Type random();
static const Zero<Derived> zero(int rows, int cols);
static const Zero<Derived> zero(int size);
static const Zero<Derived> zero();
@ -359,11 +356,13 @@ template<typename Derived> class MatrixBase
template<typename NewType>
const CwiseUnaryOp<ei_scalar_cast_op<NewType>, Derived> cast() const;
const Eval<Derived> eval() const EIGEN_ALWAYS_INLINE;
const typename ei_eval_unless_lazy<Derived>::Type eval() const EIGEN_ALWAYS_INLINE;
const EvalOMP<Derived> evalOMP() const EIGEN_ALWAYS_INLINE;
template<typename OtherDerived>
void swap(const MatrixBase<OtherDerived>& other);
const Lazy<Derived> lazy() const;
//@}
/// \name Coefficient-wise operations

View File

@ -69,8 +69,8 @@ struct ei_product_unroller<Index, 0, Lhs, Rhs>
* \param EvalMode internal use only
*
* This class represents an expression of the product of two matrices.
* It is the return type of MatrixBase::lazyProduct(), which is used internally by
* the operator* between matrices, and most of the time this is the only way it is used.
* It is the return type of the operator* between matrices, and most of the time
* this is the only way it is used.
*
* \sa class Sum, class Difference
*/
@ -85,7 +85,7 @@ struct ei_traits<Product<Lhs, Rhs, EvalMode> >
MaxColsAtCompileTime = Rhs::MaxColsAtCompileTime,
Flags = (RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic)
? (unsigned int)(Lhs::Flags | Rhs::Flags)
: (unsigned int)(Lhs::Flags | Rhs::Flags) & ~Large
: (unsigned int)(Lhs::Flags | Rhs::Flags) & ~LargeBit
};
};
@ -148,36 +148,19 @@ template<typename Lhs, typename Rhs, int EvalMode> class Product : ei_no_assignm
const typename Rhs::XprCopy m_rhs;
};
/** \returns an expression of the matrix product of \c this and \a other, in this order.
*
* This function is used internally by the operator* between matrices. The difference between
* lazyProduct() and that operator* is that lazyProduct() only constructs and returns an
* expression without actually computing the matrix product, while the operator* between
* matrices immediately evaluates the product and returns the resulting matrix.
*
* \sa class Product
*/
template<typename Derived>
template<typename OtherDerived>
const Product<Derived, OtherDerived>
MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const
{
return Product<Derived, OtherDerived>(derived(), other.derived());
}
/** \returns the matrix product of \c *this and \a other.
*
* \note This function causes an immediate evaluation. If you want to perform a matrix product
* without immediate evaluation, use MatrixBase::lazyProduct() instead.
* without immediate evaluation, call .lazy() on one of the matrices before taking the product.
*
* \sa lazyProduct(), operator*=(const MatrixBase&)
* \sa lazy(), operator*=(const MatrixBase&)
*/
template<typename Derived>
template<typename OtherDerived>
const Eval<Product<Derived, OtherDerived> >
const typename ei_eval_unless_lazy<Product<Derived, OtherDerived> >::Type
MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
{
return lazyProduct(other).eval();
return Product<Derived, OtherDerived>(derived(), other.derived()).eval();
}
/** replaces \c *this by \c *this * \a other.

View File

@ -35,13 +35,13 @@
template<typename MatrixType>
struct ei_traits<Random<MatrixType> >
{
typedef typename MatrixType::Scalar Scalar;
typedef typename ei_traits<MatrixType>::Scalar Scalar;
enum {
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
ColsAtCompileTime = MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
Flags = MatrixType::Flags
RowsAtCompileTime = ei_traits<MatrixType>::RowsAtCompileTime,
ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime,
MaxRowsAtCompileTime = ei_traits<MatrixType>::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ei_traits<MatrixType>::MaxColsAtCompileTime,
Flags = ei_traits<MatrixType>::Flags
};
};
@ -92,7 +92,7 @@ template<typename MatrixType> class Random : ei_no_assignment_operator,
* \sa ei_random(), ei_random(int)
*/
template<typename Derived>
const Eval<Random<Derived> >
const typename ei_eval_unless_lazy<Random<Derived> >::Type
MatrixBase<Derived>::random(int rows, int cols)
{
return Random<Derived>(rows, cols).eval();
@ -115,7 +115,7 @@ MatrixBase<Derived>::random(int rows, int cols)
* \sa ei_random(), ei_random(int,int)
*/
template<typename Derived>
const Eval<Random<Derived> >
const typename ei_eval_unless_lazy<Random<Derived> >::Type
MatrixBase<Derived>::random(int size)
{
ei_assert(IsVectorAtCompileTime);
@ -135,7 +135,7 @@ MatrixBase<Derived>::random(int size)
* \sa ei_random(int), ei_random(int,int)
*/
template<typename Derived>
const Eval<Random<Derived> >
const typename ei_eval_unless_lazy<Random<Derived> >::Type
MatrixBase<Derived>::random()
{
return Random<Derived>(RowsAtCompileTime, ColsAtCompileTime).eval();

View File

@ -95,7 +95,7 @@ struct ei_traits<PartialRedux<Direction, BinaryOp, MatrixType> >
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
Flags = (RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic)
? (unsigned int)MatrixType::Flags
: (unsigned int)MatrixType::Flags & ~Large
: (unsigned int)MatrixType::Flags & ~LargeBit
};
};

View File

@ -46,7 +46,7 @@ struct ei_traits<Transpose<MatrixType> >
ColsAtCompileTime = MatrixType::RowsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxColsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
Flags = MatrixType::Flags ^ RowMajor
Flags = MatrixType::Flags ^ RowMajorBit
};
};

View File

@ -37,7 +37,7 @@
#endif
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER RowMajor
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER RowMajorBit
#else
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER 0
#endif
@ -128,9 +128,9 @@ friend class Eigen::MatrixBase<Derived>;
const int Dynamic = -10;
// matrix/expression flags
const unsigned int RowMajor = 0x1;
const unsigned int Lazy = 0x2;
const unsigned int Large = 0x4;
const unsigned int RowMajorBit = 0x1;
const unsigned int LazyBit = 0x2;
const unsigned int LargeBit = 0x4;
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };

View File

@ -13,13 +13,13 @@ void benchBasic_loop(const MatrixType& I, MatrixType& m, int iterations)
{
asm("#begin_bench_loop LazyEval");
if (MatrixType::SizeAtCompileTime!=Eigen::Dynamic) asm("#fixedsize");
m = (I + 0.00005 * (m + m.lazyProduct(m))).eval();
m = (I + 0.00005 * (m + m.lazy() * m)).eval();
}
else if (Mode==OmpEval)
{
asm("#begin_bench_loop OmpEval");
if (MatrixType::SizeAtCompileTime!=Eigen::Dynamic) asm("#fixedsize");
m = (I + 0.00005 * (m + m.lazyProduct(m))).evalOMP();
m = (I + 0.00005 * (m + m.lazy() * m)).evalOMP();
}
else
{

View File

@ -1,17 +1,17 @@
#!/bin/bash
echo "Fixed size 3x3, ColumnMajor, -DNDEBUG"
echo "Fixed size 3x3, column-major, -DNDEBUG"
$CXX -O3 -I .. -DNDEBUG benchmark.cpp -o benchmark && time ./benchmark >/dev/null
echo "Fixed size 3x3, ColumnMajor, with asserts"
echo "Fixed size 3x3, column-major, with asserts"
$CXX -O3 -I .. benchmark.cpp -o benchmark && time ./benchmark >/dev/null
echo "Fixed size 3x3, RowMajor, -DNDEBUG"
echo "Fixed size 3x3, row-major, -DNDEBUG"
$CXX -O3 -I .. -DEIGEN_DEFAULT_TO_ROW_MAJOR -DNDEBUG benchmark.cpp -o benchmark && time ./benchmark >/dev/null
echo "Fixed size 3x3, RowMajor, with asserts"
echo "Fixed size 3x3, row-major, with asserts"
$CXX -O3 -I .. -DEIGEN_DEFAULT_TO_ROW_MAJOR benchmark.cpp -o benchmark && time ./benchmark >/dev/null
echo "Dynamic size 20x20, ColumnMajor, -DNDEBUG"
echo "Dynamic size 20x20, column-major, -DNDEBUG"
$CXX -O3 -I .. -DNDEBUG benchmarkX.cpp -o benchmarkX && time ./benchmarkX >/dev/null
echo "Dynamic size 20x20, ColumnMajor, with asserts"
echo "Dynamic size 20x20, column-major, with asserts"
$CXX -O3 -I .. benchmarkX.cpp -o benchmarkX && time ./benchmarkX >/dev/null
echo "Dynamic size 20x20, RowMajor, -DNDEBUG"
echo "Dynamic size 20x20, row-major, -DNDEBUG"
$CXX -O3 -I .. -DEIGEN_DEFAULT_TO_ROW_MAJOR -DNDEBUG benchmarkX.cpp -o benchmarkX && time ./benchmarkX >/dev/null
echo "Dynamic size 20x20, RowMajor, with asserts"
echo "Dynamic size 20x20, row-major, with asserts"
$CXX -O3 -I .. -DEIGEN_DEFAULT_TO_ROW_MAJOR benchmarkX.cpp -o benchmarkX && time ./benchmarkX >/dev/null

View File

@ -110,7 +110,7 @@ void EigenTest::testBasicStuff()
m3 = Matrix3d::random();
m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajor>::map(data)) );
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
Vector3d vec[3];
vec[0] << 1, 4, 7;
@ -118,7 +118,7 @@ void EigenTest::testBasicStuff()
vec[2] << 3, 6, 9;
m3 = Matrix3d::random();
m3 << vec[0], vec[1], vec[2];
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajor>::map(data)) );
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
vec[0] << 1, 2, 3;
vec[1] << 4, 5, 6;
@ -127,7 +127,7 @@ void EigenTest::testBasicStuff()
m3 << vec[0].transpose(),
4, 5, 6,
vec[2].transpose();
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajor>::map(data)) );
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
}
}

View File

@ -127,7 +127,7 @@
#endif // EIGEN_NO_ASSERTION_CHECKING
//#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER RowMajor
//#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER RowMajorBit
#define EIGEN_INTERNAL_DEBUGGING
#include <Eigen/Core>

View File

@ -63,7 +63,7 @@ template<typename MatrixType> void product(const MatrixType& m)
m3 = m1;
m3 *= (m1.transpose() * m2);
VERIFY_IS_APPROX(m3, m1*(m1.transpose()*m2));
VERIFY_IS_APPROX(m3, m1.lazyProduct(m1.transpose()*m2));
VERIFY_IS_APPROX(m3, m1.lazy() * (m1.transpose()*m2));
// continue testing Product.h: distributivity
VERIFY_IS_APPROX(square*(m1 + m2), square*m1+square*m2);
@ -73,10 +73,11 @@ template<typename MatrixType> void product(const MatrixType& m)
VERIFY_IS_APPROX(s1*(square*m1), (s1*square)*m1);
VERIFY_IS_APPROX(s1*(square*m1), square*(m1*s1));
// continue testing Product.h: lazyProduct
VERIFY_IS_APPROX(square.lazyProduct(m1), square*m1);
// continue testing Product.h: lazy product
VERIFY_IS_APPROX(square.lazy() * m1, square*m1);
VERIFY_IS_APPROX(square * m1.lazy(), square*m1);
// again, test operator() to check const-qualification
s1 += square.lazyProduct(m1)(r,c);
s1 += (square.lazy() * m1)(r,c);
// test Product.h together with Identity.h
VERIFY_IS_APPROX(m1, identity*m1);

View File

@ -86,7 +86,7 @@ template<typename MatrixType> void submatrices(const MatrixType& m)
//check row() and col()
VERIFY_IS_APPROX(m1.col(c1).transpose(), m1.transpose().row(c1));
VERIFY_IS_APPROX(square.row(r1).dot(m1.col(c1)), square.lazyProduct(m1.conjugate())(r1,c1));
VERIFY_IS_APPROX(square.row(r1).dot(m1.col(c1)), (square.lazy() * m1.conjugate())(r1,c1));
//check operator(), both constant and non-constant, on row() and col()
m1.row(r1) += s1 * m1.row(r2);
m1.col(c1) += s1 * m1.col(c2);