Fix a few regression regarding temporaries and products

This commit is contained in:
Gael Guennebaud 2013-12-14 22:53:47 +01:00
parent 27c068e9d6
commit d357bbd9c0
4 changed files with 98 additions and 31 deletions

View File

@ -82,7 +82,8 @@ private:
public: public:
enum { enum {
value = selector::ret value = selector::ret,
ret = selector::ret
}; };
#ifdef EIGEN_DEBUG_PRODUCT #ifdef EIGEN_DEBUG_PRODUCT
static void debug() static void debug()
@ -98,31 +99,31 @@ public:
#endif #endif
}; };
template<typename Lhs, typename Rhs> struct product_tag // template<typename Lhs, typename Rhs> struct product_tag
{ // {
private: // private:
//
typedef typename remove_all<Lhs>::type _Lhs; // typedef typename remove_all<Lhs>::type _Lhs;
typedef typename remove_all<Rhs>::type _Rhs; // typedef typename remove_all<Rhs>::type _Rhs;
enum { // enum {
Rows = _Lhs::RowsAtCompileTime, // Rows = _Lhs::RowsAtCompileTime,
Cols = _Rhs::ColsAtCompileTime, // Cols = _Rhs::ColsAtCompileTime,
Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, _Rhs::RowsAtCompileTime) // Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, _Rhs::RowsAtCompileTime)
}; // };
//
enum { // enum {
rows_select = Rows==1 ? int(Rows) : int(Large), // rows_select = Rows==1 ? int(Rows) : int(Large),
cols_select = Cols==1 ? int(Cols) : int(Large), // cols_select = Cols==1 ? int(Cols) : int(Large),
depth_select = Depth==1 ? int(Depth) : int(Large) // depth_select = Depth==1 ? int(Depth) : int(Large)
}; // };
typedef product_type_selector<rows_select, cols_select, depth_select> selector; // typedef product_type_selector<rows_select, cols_select, depth_select> selector;
//
public: // public:
enum { // enum {
ret = selector::ret // ret = selector::ret
}; // };
//
}; // };
/* The following allows to select the kind of product at compile time /* The following allows to select the kind of product at compile time
* based on the three dimensions of the product. * based on the three dimensions of the product.

View File

@ -88,7 +88,7 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
namespace internal { namespace internal {
template<typename Lhs, typename Rhs, int Option, int ProductTab = internal::product_tag<Lhs,Rhs>::ret> template<typename Lhs, typename Rhs, int Option, int ProductTag = internal::product_type<Lhs,Rhs>::ret>
class dense_product_base class dense_product_base
: public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type : public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type
{}; {};

View File

@ -19,7 +19,7 @@ namespace internal {
// Like more general binary expressions, products need their own evaluator: // Like more general binary expressions, products need their own evaluator:
template< typename T, template< typename T,
int ProductTag = internal::product_tag<typename T::Lhs,typename T::Rhs>::ret, int ProductTag = internal::product_type<typename T::Lhs,typename T::Rhs>::ret,
typename LhsShape = typename evaluator_traits<typename T::Lhs>::Shape, typename LhsShape = typename evaluator_traits<typename T::Lhs>::Shape,
typename RhsShape = typename evaluator_traits<typename T::Rhs>::Shape, typename RhsShape = typename evaluator_traits<typename T::Rhs>::Shape,
typename LhsScalar = typename T::Lhs::Scalar, typename LhsScalar = typename T::Lhs::Scalar,
@ -38,7 +38,43 @@ struct evaluator<Product<Lhs, Rhs, Options> >
evaluator(const XprType& xpr) : Base(xpr) {} evaluator(const XprType& xpr) : Base(xpr) {}
}; };
// Catch scalar * ( A * B ) and transform it to (A*scalar) * B
// TODO we should apply that rule if that's really helpful
template<typename Lhs, typename Rhs, typename Scalar>
struct evaluator<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Product<Lhs, Rhs, DefaultProduct> > >
: public evaluator<Product<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>,const Lhs>, Rhs, DefaultProduct> >
{
typedef CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const Product<Lhs, Rhs, DefaultProduct> > XprType;
typedef evaluator<Product<CwiseUnaryOp<internal::scalar_multiple_op<Scalar>,const Lhs>, Rhs, DefaultProduct> > Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr)
: Base(xpr.functor().m_other * xpr.nestedExpression().lhs() * xpr.nestedExpression().rhs())
{}
};
template<typename Lhs, typename Rhs, int DiagIndex>
struct evaluator<Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> >
: public evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex> >
{
typedef Diagonal<const Product<Lhs, Rhs, DefaultProduct>, DiagIndex> XprType;
typedef evaluator<Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex> > Base;
typedef evaluator type;
typedef evaluator nestedType;
//
evaluator(const XprType& xpr)
: Base(Diagonal<const Product<Lhs, Rhs, LazyProduct>, DiagIndex>(
Product<Lhs, Rhs, LazyProduct>(xpr.nestedExpression().lhs(), xpr.nestedExpression().rhs()),
xpr.index() ))
{}
};
// Helper class to perform a matrix product with the destination at hand. // Helper class to perform a matrix product with the destination at hand.
// Depending on the sizes of the factors, there are different evaluation strategies // Depending on the sizes of the factors, there are different evaluation strategies
// as controlled by internal::product_type. // as controlled by internal::product_type.
@ -108,6 +144,23 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::sub_ass
} }
}; };
// Dense ?= scalar * Product
// TODO we should apply that rule if that's really helpful
// for instance, this is not good for inner products
template< typename DstXprType, typename Lhs, typename Rhs, typename AssignFunc, typename Scalar, typename ScalarBis>
struct Assignment<DstXprType, CwiseUnaryOp<internal::scalar_multiple_op<ScalarBis>,
const Product<Lhs,Rhs,DefaultProduct> >, AssignFunc, Dense2Dense, Scalar>
{
typedef CwiseUnaryOp<internal::scalar_multiple_op<ScalarBis>,
const Product<Lhs,Rhs,DefaultProduct> > SrcXprType;
static void run(DstXprType &dst, const SrcXprType &src, const AssignFunc& func)
{
call_assignment(dst.noalias(), (src.functor().m_other * src.nestedExpression().lhs()) * src.nestedExpression().rhs(), func);
}
};
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,InnerProduct> struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,InnerProduct>
{ {
@ -255,9 +308,9 @@ struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode>
}; };
// This specialization enforces the use of a coefficient-based evaluation strategy // This specialization enforces the use of a coefficient-based evaluation strategy
template<typename Lhs, typename Rhs> // template<typename Lhs, typename Rhs>
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,LazyCoeffBasedProductMode> // struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,LazyCoeffBasedProductMode>
: generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> {}; // : generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> {};
// Case 2: Evaluate coeff by coeff // Case 2: Evaluate coeff by coeff
// //
@ -347,6 +400,17 @@ protected:
Index m_innerDim; Index m_innerDim;
}; };
template<typename Lhs, typename Rhs>
struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, LazyCoeffBasedProductMode, DenseShape, DenseShape, typename Lhs::Scalar, typename Rhs::Scalar >
: product_evaluator<Product<Lhs, Rhs, LazyProduct>, CoeffBasedProductMode, DenseShape, DenseShape, typename Lhs::Scalar, typename Rhs::Scalar >
{
typedef Product<Lhs, Rhs, DefaultProduct> XprType;
typedef Product<Lhs, Rhs, LazyProduct> BaseProduct;
typedef product_evaluator<BaseProduct, CoeffBasedProductMode, DenseShape, DenseShape, typename Lhs::Scalar, typename Rhs::Scalar > Base;
product_evaluator(const XprType& xpr)
: Base(BaseProduct(xpr.lhs(),xpr.rhs()))
{}
};
/*************************************************************************** /***************************************************************************
* Normal product .coeff() implementation (with meta-unrolling) * Normal product .coeff() implementation (with meta-unrolling)

View File

@ -336,6 +336,7 @@ struct triangular_assignment_selector<Derived1, Derived2, SelfAdjoint|Lower, Dyn
} }
}; };
#ifdef EIGEN_ENABLE_EVALUATORS
// TODO currently a selfadjoint expression has the form SelfAdjointView<.,.> // TODO currently a selfadjoint expression has the form SelfAdjointView<.,.>
// in the future selfadjoint-ness should be defined by the expression traits // in the future selfadjoint-ness should be defined by the expression traits
// such that Transpose<SelfAdjointView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make it work) // such that Transpose<SelfAdjointView<.,.> > is valid. (currently TriangularBase::transpose() is overloaded to make it work)
@ -347,6 +348,7 @@ struct evaluator_traits<SelfAdjointView<MatrixType,Mode> >
static const int AssumeAliasing = 0; static const int AssumeAliasing = 0;
}; };
#endif // EIGEN_ENABLE_EVALUATORS
} // end namespace internal } // end namespace internal