mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-05-02 16:54:10 +08:00
Fix a few regression regarding temporaries and products
This commit is contained in:
parent
27c068e9d6
commit
d357bbd9c0
@ -82,7 +82,8 @@ private:
|
||||
|
||||
public:
|
||||
enum {
|
||||
value = selector::ret
|
||||
value = selector::ret,
|
||||
ret = selector::ret
|
||||
};
|
||||
#ifdef EIGEN_DEBUG_PRODUCT
|
||||
static void debug()
|
||||
@ -98,31 +99,31 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs> struct product_tag
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename remove_all<Lhs>::type _Lhs;
|
||||
typedef typename remove_all<Rhs>::type _Rhs;
|
||||
enum {
|
||||
Rows = _Lhs::RowsAtCompileTime,
|
||||
Cols = _Rhs::ColsAtCompileTime,
|
||||
Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, _Rhs::RowsAtCompileTime)
|
||||
};
|
||||
|
||||
enum {
|
||||
rows_select = Rows==1 ? int(Rows) : int(Large),
|
||||
cols_select = Cols==1 ? int(Cols) : int(Large),
|
||||
depth_select = Depth==1 ? int(Depth) : int(Large)
|
||||
};
|
||||
typedef product_type_selector<rows_select, cols_select, depth_select> selector;
|
||||
|
||||
public:
|
||||
enum {
|
||||
ret = selector::ret
|
||||
};
|
||||
|
||||
};
|
||||
// template<typename Lhs, typename Rhs> struct product_tag
|
||||
// {
|
||||
// private:
|
||||
//
|
||||
// typedef typename remove_all<Lhs>::type _Lhs;
|
||||
// typedef typename remove_all<Rhs>::type _Rhs;
|
||||
// enum {
|
||||
// Rows = _Lhs::RowsAtCompileTime,
|
||||
// Cols = _Rhs::ColsAtCompileTime,
|
||||
// Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, _Rhs::RowsAtCompileTime)
|
||||
// };
|
||||
//
|
||||
// enum {
|
||||
// rows_select = Rows==1 ? int(Rows) : int(Large),
|
||||
// cols_select = Cols==1 ? int(Cols) : int(Large),
|
||||
// depth_select = Depth==1 ? int(Depth) : int(Large)
|
||||
// };
|
||||
// typedef product_type_selector<rows_select, cols_select, depth_select> selector;
|
||||
//
|
||||
// public:
|
||||
// enum {
|
||||
// ret = selector::ret
|
||||
// };
|
||||
//
|
||||
// };
|
||||
|
||||
/* The following allows to select the kind of product at compile time
|
||||
* based on the three dimensions of the product.
|
||||
|
@ -88,7 +88,7 @@ class Product : public ProductImpl<_Lhs,_Rhs,Option,
|
||||
|
||||
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
|
||||
: public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type
|
||||
{};
|
||||
|
@ -19,7 +19,7 @@ namespace internal {
|
||||
|
||||
// Like more general binary expressions, products need their own evaluator:
|
||||
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 RhsShape = typename evaluator_traits<typename T::Rhs>::Shape,
|
||||
typename LhsScalar = typename T::Lhs::Scalar,
|
||||
@ -38,7 +38,43 @@ struct evaluator<Product<Lhs, Rhs, Options> >
|
||||
|
||||
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.
|
||||
// Depending on the sizes of the factors, there are different evaluation strategies
|
||||
// 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>
|
||||
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
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,LazyCoeffBasedProductMode>
|
||||
: generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> {};
|
||||
// template<typename Lhs, typename Rhs>
|
||||
// struct generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,LazyCoeffBasedProductMode>
|
||||
// : generic_product_impl<Lhs,Rhs,DenseShape,DenseShape,CoeffBasedProductMode> {};
|
||||
|
||||
// Case 2: Evaluate coeff by coeff
|
||||
//
|
||||
@ -347,6 +400,17 @@ protected:
|
||||
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)
|
||||
|
@ -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<.,.>
|
||||
// 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)
|
||||
@ -347,6 +348,7 @@ struct evaluator_traits<SelfAdjointView<MatrixType,Mode> >
|
||||
|
||||
static const int AssumeAliasing = 0;
|
||||
};
|
||||
#endif // EIGEN_ENABLE_EVALUATORS
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user