current state of the mess. One line fails in the tests, and

useless copies are made when evaluating nested expressions.
Changes:
- kill LazyBit, introduce EvalBeforeNestingBit and EvalBeforeAssigningBit
- product and random don't evaluate immediately anymore
- eval() always evaluates
- change the value of Dynamic to some large positive value,
  in preparation of future simplifications
This commit is contained in:
Benoit Jacob 2008-04-03 16:54:19 +00:00
parent b8900d0b80
commit 249dc4f482
7 changed files with 67 additions and 72 deletions

View File

@ -76,9 +76,10 @@ struct MatrixBase<Derived>::CommaInitializer
ei_assert(m_col<m_matrix.cols() ei_assert(m_col<m_matrix.cols()
&& "Too many coefficients passed to MatrixBase::operator<<"); && "Too many coefficients passed to MatrixBase::operator<<");
ei_assert(m_currentBlockRows==other.rows()); ei_assert(m_currentBlockRows==other.rows());
if (OtherDerived::RowsAtCompileTime>0 && OtherDerived::ColsAtCompileTime>0) if (OtherDerived::SizeAtCompileTime != Dynamic)
m_matrix.block< (OtherDerived::RowsAtCompileTime>0?OtherDerived::RowsAtCompileTime:1) , m_matrix.block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1,
(OtherDerived::ColsAtCompileTime>0?OtherDerived::ColsAtCompileTime:1) >(m_row, m_col) = other; OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1>
(m_row, m_col) = other;
else else
m_matrix.block(m_row, m_col, other.rows(), other.cols()) = other; m_matrix.block(m_row, m_col, other.rows(), other.cols()) = other;
m_col += other.cols(); m_col += other.cols();

View File

@ -69,40 +69,50 @@ template<typename Scalar> struct ei_scalar_quotient1_op;
template<typename Scalar> struct ei_scalar_min_op; template<typename Scalar> struct ei_scalar_min_op;
template<typename Scalar> struct ei_scalar_max_op; template<typename Scalar> struct ei_scalar_max_op;
template<typename T> struct ei_xpr_copy template<typename T> struct ei_copy_unless_matrix
{ {
typedef T type; typedef T type;
}; };
template<typename _Scalar, int _Rows, int _Cols, unsigned int _Flags, int _MaxRows, int _MaxCols> template<typename _Scalar, int _Rows, int _Cols, unsigned int _Flags, int _MaxRows, int _MaxCols>
struct ei_xpr_copy<Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> > struct ei_copy_unless_matrix<Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> >
{ {
typedef const Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> & type; typedef const Matrix<_Scalar, _Rows, _Cols, _Flags, _MaxRows, _MaxCols> & type;
}; };
template<typename T> struct ei_xpr_copy
{
typedef typename ei_meta_if<T::Flags & TemporaryBit,
T,
typename ei_copy_unless_matrix<T>::type
>::ret type;
};
template<typename T> struct ei_eval template<typename T> struct ei_eval
{ {
typedef Matrix<typename ei_traits<T>::Scalar, typedef Matrix<typename ei_traits<T>::Scalar,
ei_traits<T>::RowsAtCompileTime, ei_traits<T>::RowsAtCompileTime,
ei_traits<T>::ColsAtCompileTime, ei_traits<T>::ColsAtCompileTime,
ei_traits<T>::Flags & ~LazyBit, // unset lazy bit after evaluation ei_traits<T>::Flags & ~(EvalBeforeNestingBit | EvalBeforeAssigningBit),
ei_traits<T>::MaxRowsAtCompileTime, ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime> type; ei_traits<T>::MaxColsAtCompileTime> type;
}; };
template<typename T, int n> struct ei_eval_if_expensive template<typename T> struct ei_eval_temporary
{ {
enum { eval = n * NumTraits<typename T::Scalar>::ReadCost < (n-1) * T::CoeffReadCost }; typedef Matrix<typename ei_traits<T>::Scalar,
typedef typename ei_meta_if<eval, typename T::Eval, T>::ret type; ei_traits<T>::RowsAtCompileTime,
typedef typename ei_meta_if<eval, typename T::Eval, T&>::ret reftype; ei_traits<T>::ColsAtCompileTime,
(ei_traits<T>::Flags | TemporaryBit) & ~(EvalBeforeNestingBit | EvalBeforeAssigningBit),
ei_traits<T>::MaxRowsAtCompileTime,
ei_traits<T>::MaxColsAtCompileTime> type;
}; };
template<typename T> struct ei_eval_unless_lazy template<typename T, int n=1> struct ei_eval_if_needed_before_nesting
{ {
typedef typename ei_meta_if<ei_traits<T>::Flags & LazyBit, enum { eval = T::Flags & EvalBeforeNestingBit
T, || n * NumTraits<typename T::Scalar>::ReadCost < (n-1) * T::CoeffReadCost };
typename ei_eval<T>::type typedef typename ei_meta_if<eval, typename ei_eval_temporary<T>::type, T>::ret type;
>::ret type;
}; };
#endif // EIGEN_FORWARDDECLARATIONS_H #endif // EIGEN_FORWARDDECLARATIONS_H

View File

@ -46,7 +46,7 @@ struct ei_traits<Lazy<ExpressionType> >
ColsAtCompileTime = ExpressionType::ColsAtCompileTime, ColsAtCompileTime = ExpressionType::ColsAtCompileTime,
MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime, MaxRowsAtCompileTime = ExpressionType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime, MaxColsAtCompileTime = ExpressionType::MaxColsAtCompileTime,
Flags = ExpressionType::Flags | LazyBit, Flags = ExpressionType::Flags & ~(EvalBeforeNestingBit | EvalBeforeAssigningBit),
CoeffReadCost = ExpressionType::CoeffReadCost CoeffReadCost = ExpressionType::CoeffReadCost
}; };
}; };

View File

@ -252,7 +252,8 @@ template<typename Derived> class MatrixBase
*/ */
//@{ //@{
template<typename OtherDerived> template<typename OtherDerived>
const typename ei_eval_unless_lazy<Product<Derived, OtherDerived> >::type const Product<typename ei_eval_if_needed_before_nesting<Derived, OtherDerived::ColsAtCompileTime>::type,
typename ei_eval_if_needed_before_nesting<OtherDerived, ei_traits<Derived>::ColsAtCompileTime>::type>
operator*(const MatrixBase<OtherDerived> &other) const; operator*(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived> template<typename OtherDerived>
@ -312,9 +313,9 @@ template<typename Derived> class MatrixBase
/// \name Generating special matrices /// \name Generating special matrices
//@{ //@{
static const typename ei_eval_unless_lazy<Random<Derived> >::type random(int rows, int cols); static const Random<Derived> random(int rows, int cols);
static const typename ei_eval_unless_lazy<Random<Derived> >::type random(int size); static const Random<Derived> random(int size);
static const typename ei_eval_unless_lazy<Random<Derived> >::type random(); static const Random<Derived> random();
static const Zero<Derived> zero(int rows, int cols); static const Zero<Derived> zero(int rows, int cols);
static const Zero<Derived> zero(int size); static const Zero<Derived> zero(int size);
static const Zero<Derived> zero(); static const Zero<Derived> zero();
@ -358,9 +359,9 @@ template<typename Derived> class MatrixBase
template<typename NewType> template<typename NewType>
const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived> cast() const; const CwiseUnaryOp<ei_scalar_cast_op<typename ei_traits<Derived>::Scalar, NewType>, Derived> cast() const;
const typename ei_eval_unless_lazy<Derived>::type eval() const EIGEN_ALWAYS_INLINE const typename ei_eval<Derived>::type eval() const EIGEN_ALWAYS_INLINE
{ {
return typename ei_eval_unless_lazy<Derived>::type(derived()); return typename ei_eval<Derived>::type(derived());
} }
template<typename OtherDerived> template<typename OtherDerived>

View File

@ -74,37 +74,26 @@ struct ei_product_unroller<Index, 0, Lhs, Rhs>
* *
* \sa class Sum, class Difference * \sa class Sum, class Difference
*/ */
template<typename Lhs, typename Rhs> struct ei_product_eval_mode
{
enum{ value = Lhs::MaxRowsAtCompileTime >= 8 && Rhs::MaxColsAtCompileTime >= 8
? CacheOptimal : UnrolledDotProduct };
};
template<typename Lhs, typename Rhs, int EvalMode> template<typename Lhs, typename Rhs, int EvalMode>
struct ei_traits<Product<Lhs, Rhs, EvalMode> > struct ei_traits<Product<Lhs, Rhs, EvalMode> >
{ {
typedef typename Lhs::Scalar Scalar; typedef typename Lhs::Scalar Scalar;
#if 0
typedef typename ei_meta_if<
(int)NumTraits<Scalar>::ReadCost < (int)Lhs::CoeffReadCost,
typename Lhs::Eval,
Lhs>::ret ActualLhs;
typedef typename ei_meta_if<
(int)NumTraits<Scalar>::ReadCost < (int)Lhs::CoeffReadCost,
typename Lhs::Eval,
typename Lhs::XprCopy>::ret ActualLhsXprCopy;
typedef typename ei_meta_if<
(int)NumTraits<Scalar>::ReadCost < (int)Rhs::CoeffReadCost,
typename Rhs::Eval,
Rhs>::ret ActualRhs;
typedef typename ei_meta_if<
(int)NumTraits<Scalar>::ReadCost < (int)Rhs::CoeffReadCost,
typename Rhs::Eval,
typename Rhs::XprCopy>::ret ActualRhsXprCopy;
#endif
enum { enum {
RowsAtCompileTime = Lhs::RowsAtCompileTime, RowsAtCompileTime = Lhs::RowsAtCompileTime,
ColsAtCompileTime = Rhs::ColsAtCompileTime, ColsAtCompileTime = Rhs::ColsAtCompileTime,
MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime, MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime,
MaxColsAtCompileTime = Rhs::MaxColsAtCompileTime, MaxColsAtCompileTime = Rhs::MaxColsAtCompileTime,
Flags = (RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic) Flags = ( (RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic)
? (unsigned int)(Lhs::Flags | Rhs::Flags) ? (unsigned int)(Lhs::Flags | Rhs::Flags)
: (unsigned int)(Lhs::Flags | Rhs::Flags) & ~LargeBit, : (unsigned int)(Lhs::Flags | Rhs::Flags) & ~LargeBit )
| EvalBeforeAssigningBit
| (ei_product_eval_mode<Lhs, Rhs>::value == (int)CacheOptimal ? EvalBeforeNestingBit : 0),
CoeffReadCost CoeffReadCost
= Lhs::ColsAtCompileTime == Dynamic = Lhs::ColsAtCompileTime == Dynamic
? Dynamic ? Dynamic
@ -114,25 +103,15 @@ struct ei_traits<Product<Lhs, Rhs, EvalMode> >
}; };
}; };
template<typename Lhs, typename Rhs> struct ei_product_eval_mode
{
enum{ value = Lhs::MaxRowsAtCompileTime == Dynamic || Rhs::MaxColsAtCompileTime == Dynamic
? CacheOptimal : UnrolledDotProduct };
};
template<typename Lhs, typename Rhs, int EvalMode> class Product : ei_no_assignment_operator, template<typename Lhs, typename Rhs, int EvalMode> class Product : ei_no_assignment_operator,
public MatrixBase<Product<Lhs, Rhs, EvalMode> > public MatrixBase<Product<Lhs, Rhs, EvalMode> >
{ {
public: public:
EIGEN_GENERIC_PUBLIC_INTERFACE(Product) EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
#if 0
typedef typename ei_traits<Product>::ActualLhs ActualLhs; template<typename ArgLhs, typename ArgRhs>
typedef typename ei_traits<Product>::ActualRhs ActualRhs; Product(const ArgLhs& lhs, const ArgRhs& rhs)
typedef typename ei_traits<Product>::ActualLhsXprCopy ActualLhsXprCopy;
typedef typename ei_traits<Product>::ActualRhsXprCopy ActualRhsXprCopy;
#endif
Product(const Lhs& lhs, const Rhs& rhs)
: m_lhs(lhs), m_rhs(rhs) : m_lhs(lhs), m_rhs(rhs)
{ {
ei_assert(lhs.cols() == rhs.rows()); ei_assert(lhs.cols() == rhs.rows());
@ -181,13 +160,14 @@ template<typename Lhs, typename Rhs, int EvalMode> class Product : ei_no_assignm
*/ */
template<typename Derived> template<typename Derived>
template<typename OtherDerived> template<typename OtherDerived>
const typename ei_eval_unless_lazy<Product<Derived, OtherDerived> >::type const Product<typename ei_eval_if_needed_before_nesting<Derived, OtherDerived::ColsAtCompileTime>::type,
typename ei_eval_if_needed_before_nesting<OtherDerived, ei_traits<Derived>::ColsAtCompileTime>::type>
MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
{ {
typedef ei_eval_if_expensive<Derived, OtherDerived::ColsAtCompileTime> Lhs; typedef ei_eval_if_needed_before_nesting<Derived, OtherDerived::ColsAtCompileTime> Lhs;
typedef ei_eval_if_expensive<OtherDerived, Derived::RowsAtCompileTime> Rhs; typedef ei_eval_if_needed_before_nesting<OtherDerived, Derived::RowsAtCompileTime> Rhs;
return Product<typename Lhs::type, typename Rhs::type> return Product<typename Lhs::type, typename Rhs::type>
(typename Lhs::reftype(derived()), typename Rhs::reftype(other.derived())).eval(); (derived(), other.derived());
} }
/** replaces \c *this by \c *this * \a other. /** replaces \c *this by \c *this * \a other.

View File

@ -41,7 +41,7 @@ struct ei_traits<Random<MatrixType> >
ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime, ColsAtCompileTime = ei_traits<MatrixType>::ColsAtCompileTime,
MaxRowsAtCompileTime = ei_traits<MatrixType>::MaxRowsAtCompileTime, MaxRowsAtCompileTime = ei_traits<MatrixType>::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ei_traits<MatrixType>::MaxColsAtCompileTime, MaxColsAtCompileTime = ei_traits<MatrixType>::MaxColsAtCompileTime,
Flags = ei_traits<MatrixType>::Flags, Flags = ei_traits<MatrixType>::Flags | EvalBeforeNestingBit,
CoeffReadCost = 2 * NumTraits<Scalar>::MulCost // FIXME: arbitrary value CoeffReadCost = 2 * NumTraits<Scalar>::MulCost // FIXME: arbitrary value
}; };
}; };
@ -93,10 +93,10 @@ template<typename MatrixType> class Random : ei_no_assignment_operator,
* \sa ei_random(), ei_random(int) * \sa ei_random(), ei_random(int)
*/ */
template<typename Derived> template<typename Derived>
const typename ei_eval_unless_lazy<Random<Derived> >::type const Random<Derived>
MatrixBase<Derived>::random(int rows, int cols) MatrixBase<Derived>::random(int rows, int cols)
{ {
return Random<Derived>(rows, cols).eval(); return Random<Derived>(rows, cols);
} }
/** \returns a random vector (not an expression, the vector is immediately evaluated). /** \returns a random vector (not an expression, the vector is immediately evaluated).
@ -116,12 +116,12 @@ MatrixBase<Derived>::random(int rows, int cols)
* \sa ei_random(), ei_random(int,int) * \sa ei_random(), ei_random(int,int)
*/ */
template<typename Derived> template<typename Derived>
const typename ei_eval_unless_lazy<Random<Derived> >::type const Random<Derived>
MatrixBase<Derived>::random(int size) MatrixBase<Derived>::random(int size)
{ {
ei_assert(IsVectorAtCompileTime); ei_assert(IsVectorAtCompileTime);
if(RowsAtCompileTime == 1) return Random<Derived>(1, size).eval(); if(RowsAtCompileTime == 1) return Random<Derived>(1, size);
else return Random<Derived>(size, 1).eval(); else return Random<Derived>(size, 1);
} }
/** \returns a fixed-size random matrix or vector /** \returns a fixed-size random matrix or vector
@ -136,10 +136,10 @@ MatrixBase<Derived>::random(int size)
* \sa ei_random(int), ei_random(int,int) * \sa ei_random(int), ei_random(int,int)
*/ */
template<typename Derived> template<typename Derived>
const typename ei_eval_unless_lazy<Random<Derived> >::type const Random<Derived>
MatrixBase<Derived>::random() MatrixBase<Derived>::random()
{ {
return Random<Derived>(RowsAtCompileTime, ColsAtCompileTime).eval(); return Random<Derived>(RowsAtCompileTime, ColsAtCompileTime);
} }
/** Sets all coefficients in this expression to random values. /** Sets all coefficients in this expression to random values.

View File

@ -127,12 +127,15 @@ friend class Eigen::MatrixBase<Derived>;
#define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b) #define EIGEN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
const int Dynamic = -10; const int Dynamic = 10000;
// matrix/expression flags // matrix/expression flags
const unsigned int RowMajorBit = 0x1; const unsigned int RowMajorBit = 0x1;
const unsigned int LazyBit = 0x2; const unsigned int EvalBeforeNestingBit = 0x2;
const unsigned int LargeBit = 0x4; const unsigned int EvalBeforeAssigningBit = 0x4;
const unsigned int LargeBit = 0x8;
const unsigned int TemporaryBit = 0x10;
enum { ConditionalJumpCost = 5 }; enum { ConditionalJumpCost = 5 };