First step toward the generalization of evaluators to triangular, sparse and other fancyness.

Remove product_tag template parameter to Product.
This commit is contained in:
Gael Guennebaud 2013-11-29 17:50:59 +01:00
parent fb6e32a62f
commit c15c65990f
5 changed files with 109 additions and 36 deletions

View File

@ -646,7 +646,7 @@ struct SparseShape {};
// Based on the respective shapes of the destination and source,
// the class AssignmentKind determine the kind of assignment mechanism.
// AssignmentKind must define a Kind typedef.
template<int DstShape, int SrcShape> struct AssignmentKind;
template<typename DstShape, typename SrcShape> struct AssignmentKind;
// AssignmentKind<.,.>::Kind can be one of the following:
struct Dense2Dense {};
@ -655,9 +655,11 @@ template<int DstShape, int SrcShape> struct AssignmentKind;
struct Sparse2Dense {};
struct Sparse2Sparse {};
template<> struct AssignmentKind<Dense,Dense> { typedef Dense2Dense Kind; };
// This is the main assignment class
template< typename DstXprType, typename SrcXprType, typename Functor,
typename Kind = Dense2Dense,//AssignmentKind< evaluator<A>::Shape , evaluator<B>::Shape >::Kind,
typename Kind = typename AssignmentKind< typename evaluator_traits<DstXprType>::Shape , typename evaluator_traits<SrcXprType>::Shape >::Kind,
typename Scalar = typename DstXprType::Scalar>
struct Assignment;

View File

@ -14,20 +14,70 @@
#define EIGEN_COREEVALUATORS_H
namespace Eigen {
namespace internal {
template<typename T> struct evaluator;
struct IndexBased {};
struct IteratorBased {};
// This class returns the evaluator kind from the expression storage kind.
// Default assumes index based accessors
template<typename StorageKind>
struct storage_kind_to_evaluator_kind {
typedef IndexBased Kind;
};
// TODO to be moved to SparseCore:
/*
template<>
struct storage_kind_to_evaluator_kind<Sparse> {
typedef IteratorBased Kind
};
*/
// This class returns the evaluator shape from the expression storage kind.
// It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc.
template<typename StorageKind> struct storage_kind_to_shape;
template<>
struct storage_kind_to_shape<Dense> {
typedef Dense Shape;
};
// TODO to be moved to SparseCore:
/*
template<>
struct storage_kind_to_shape<Sparse> {
typedef Sparse Shape;
};
*/
template<typename T> struct evaluator_traits;
template< typename T,
typename Kind = typename evaluator_traits<T>::Kind,
typename Scalar = typename T::Scalar> struct evaluator;
template< typename T,
typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
typename LhsScalar = typename T::Lhs::Scalar,
typename RhsScalar = typename T::Rhs::Scalar> struct binary_evaluator;
// evaluator_traits<T> contains traits for evaluator<T>
template<typename T>
template<typename T>
struct evaluator_traits_base
{
// TODO check whether these two indirections are really needed.
// Basically, if nobody overwrite type and nestedType, then, they can be dropped
typedef evaluator<T> type;
typedef evaluator<T> nestedType;
// typedef evaluator<T> type;
// typedef evaluator<T> nestedType;
// by default, get evalautor kind and shape from storage
typedef typename storage_kind_to_evaluator_kind<typename T::StorageKind>::Kind Kind;
typedef typename storage_kind_to_shape<typename T::StorageKind>::Shape Shape;
// 1 if assignment A = B assumes aliasing when B is of type T and thus B needs to be evaluated into a
// temporary; 0 if not.
@ -58,8 +108,10 @@ struct evaluator<const T>
template<typename ExpressionType>
struct evaluator_base
{
typedef typename evaluator_traits<ExpressionType>::type type;
typedef typename evaluator_traits<ExpressionType>::nestedType nestedType;
// typedef typename evaluator_traits<ExpressionType>::type type;
// typedef typename evaluator_traits<ExpressionType>::nestedType nestedType;
typedef evaluator<ExpressionType> type;
typedef evaluator<ExpressionType> nestedType;
typedef typename ExpressionType::Index Index;
// TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices.

View File

@ -12,7 +12,7 @@
namespace Eigen {
template<typename Lhs, typename Rhs, int Option, int ProductTag, typename StorageKind> class ProductImpl;
template<typename Lhs, typename Rhs, int Option, typename StorageKind> class ProductImpl;
/** \class Product
* \ingroup Core_Module
@ -26,14 +26,13 @@ template<typename Lhs, typename Rhs, int Option, int ProductTag, typename Storag
*
* The other template parameters are:
* \tparam Option can be DefaultProduct or LazyProduct
* \tparam ProductTag can be InnerProduct, OuterProduct, GemvProduct, GemmProduct. It is used to ease expression manipulations.
*
*/
// Use ProductReturnType to get correct traits, in particular vectorization flags
namespace internal {
template<typename Lhs, typename Rhs, int Option, int ProductTag>
struct traits<Product<Lhs, Rhs, Option, ProductTag> >
template<typename Lhs, typename Rhs, int Option>
struct traits<Product<Lhs, Rhs, Option> >
: traits<typename ProductReturnType<Lhs, Rhs>::Type>
{
// We want A+B*C to be of type Product<Matrix, Sum> and not Product<Matrix, Matrix>
@ -45,18 +44,23 @@ struct traits<Product<Lhs, Rhs, Option, ProductTag> >
} // end namespace internal
template<typename Lhs, typename Rhs, int Option, int ProductTag>
class Product : public ProductImpl<Lhs,Rhs,Option,ProductTag,
typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
typename internal::traits<Rhs>::StorageKind>::ret>
template<typename _Lhs, typename _Rhs, int Option>
class Product : public ProductImpl<_Lhs,_Rhs,Option,
typename internal::promote_storage_type<typename internal::traits<_Lhs>::StorageKind,
typename internal::traits<_Rhs>::StorageKind>::ret>
{
public:
typedef _Lhs Lhs;
typedef _Rhs Rhs;
typedef typename ProductImpl<
Lhs, Rhs, Option, ProductTag,
Lhs, Rhs, Option,
typename internal::promote_storage_type<typename Lhs::StorageKind,
typename Rhs::StorageKind>::ret>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(Product)
typedef typename Lhs::Nested LhsNested;
typedef typename Rhs::Nested RhsNested;
@ -82,13 +86,13 @@ class Product : public ProductImpl<Lhs,Rhs,Option,ProductTag,
RhsNested m_rhs;
};
template<typename Lhs, typename Rhs, int Option, int ProductTag>
class ProductImpl<Lhs,Rhs,Option,ProductTag,Dense> : public internal::dense_xpr_base<Product<Lhs,Rhs,Option,ProductTag> >::type
template<typename Lhs, typename Rhs, int Option>
class ProductImpl<Lhs,Rhs,Option,Dense> : public internal::dense_xpr_base<Product<Lhs,Rhs,Option> >::type
{
typedef Product<Lhs, Rhs> Derived;
public:
typedef typename internal::dense_xpr_base<Product<Lhs, Rhs, Option, ProductTag> >::type Base;
typedef typename internal::dense_xpr_base<Product<Lhs, Rhs, Option> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
};

View File

@ -16,7 +16,28 @@
namespace Eigen {
namespace internal {
// Like more general binary expressions, products need they own evaluator:
template< typename T,
int ProductTag = internal::product_tag<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,
typename RhsScalar = typename T::Rhs::Scalar
> struct product_evaluator;
template<typename Lhs, typename Rhs, int Options>
struct evaluator<Product<Lhs, Rhs, Options> >
: public product_evaluator<Product<Lhs, Rhs, Options> >
{
typedef Product<Lhs, Rhs, Options> XprType;
typedef product_evaluator<XprType> Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr) : Base(xpr) {}
};
// Helper class to perform a dense product with the destination at hand.
// Depending on the sizes of the factors, there are different evaluation strategies
@ -27,17 +48,14 @@ struct dense_product_impl;
// The evaluator for default dense products creates a temporary and call dense_product_impl
template<typename Lhs, typename Rhs, int ProductTag>
struct evaluator<Product<Lhs, Rhs, DefaultProduct, ProductTag> >
: public evaluator<typename Product<Lhs, Rhs, DefaultProduct, ProductTag>::PlainObject>::type
struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, Dense, Dense, typename Lhs::Scalar, typename Rhs::Scalar>
: public evaluator<typename Product<Lhs, Rhs, DefaultProduct>::PlainObject>::type
{
typedef Product<Lhs, Rhs, DefaultProduct, ProductTag> XprType;
typedef Product<Lhs, Rhs, DefaultProduct> XprType;
typedef typename XprType::PlainObject PlainObject;
typedef typename evaluator<PlainObject>::type Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr)
product_evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
@ -199,13 +217,13 @@ template<int StorageOrder, int UnrollingIndex, typename Lhs, typename Rhs, typen
struct etor_product_packet_impl;
template<typename Lhs, typename Rhs, int ProductTag>
struct evaluator<Product<Lhs, Rhs, LazyProduct, ProductTag> >
: evaluator_base<Product<Lhs, Rhs, LazyProduct, ProductTag> >
struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, Dense, Dense, typename Lhs::Scalar, typename Rhs::Scalar >
: evaluator_base<Product<Lhs, Rhs, LazyProduct> >
{
typedef Product<Lhs, Rhs, LazyProduct, ProductTag> XprType;
typedef Product<Lhs, Rhs, LazyProduct> XprType;
typedef CoeffBasedProduct<Lhs, Rhs, 0> CoeffBasedProductType;
evaluator(const XprType& xpr)
product_evaluator(const XprType& xpr)
: m_lhsImpl(xpr.lhs()),
m_rhsImpl(xpr.rhs()),
m_innerDim(xpr.lhs().cols())

View File

@ -94,10 +94,7 @@ namespace internal {
template<typename Lhs, typename Rhs> struct product_tag;
}
template<typename Lhs, typename Rhs,
int Option = DefaultProduct,
int ProductTag = internal::product_tag<Lhs,Rhs>::ret
> class Product;
template<typename Lhs, typename Rhs, int Option = DefaultProduct> class Product;
template<typename Lhs, typename Rhs, int Mode> class GeneralProduct; // TODO deprecated
template<typename Lhs, typename Rhs, int NestingFlags> class CoeffBasedProduct; // TODO deprecated