Move CoeffReadCost mechanism to evaluators

This commit is contained in:
Gael Guennebaud 2014-03-10 23:24:40 +01:00
parent 354bd8a428
commit da6ec81282
27 changed files with 321 additions and 120 deletions

View File

@ -64,8 +64,10 @@ template<typename Derived> class ArrayBase
using Base::MaxSizeAtCompileTime;
using Base::IsVectorAtCompileTime;
using Base::Flags;
#ifndef EIGEN_TEST_EVALUATORS
using Base::CoeffReadCost;
#endif
using Base::derived;
using Base::const_cast_derived;
using Base::rows;

View File

@ -508,9 +508,6 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
#ifdef EIGEN_TEST_EVALUATORS
#ifdef EIGEN_DEBUG_ASSIGN
internal::copy_using_evaluator_traits<Derived, OtherDerived>::debug();
#endif
eigen_assert(rows() == other.rows() && cols() == other.cols());
internal::call_dense_assignment_loop(derived(),other.derived());

View File

@ -24,37 +24,45 @@ namespace internal {
// copy_using_evaluator_traits is based on assign_traits
template <typename Derived, typename OtherDerived, typename AssignFunc>
template <typename DstEvaluator, typename SrcEvaluator, typename AssignFunc>
struct copy_using_evaluator_traits
{
typedef typename DstEvaluator::XprType Dst;
typedef typename SrcEvaluator::XprType Src;
// TODO, we should get these flags from the evaluators
enum {
DstFlags = Dst::Flags,
SrcFlags = Src::Flags
};
public:
enum {
DstIsAligned = Derived::Flags & AlignedBit,
DstHasDirectAccess = Derived::Flags & DirectAccessBit,
SrcIsAligned = OtherDerived::Flags & AlignedBit,
DstIsAligned = DstFlags & AlignedBit,
DstHasDirectAccess = DstFlags & DirectAccessBit,
SrcIsAligned = SrcFlags & AlignedBit,
JointAlignment = bool(DstIsAligned) && bool(SrcIsAligned) ? Aligned : Unaligned
};
private:
enum {
InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime)
: int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime)
: int(Derived::RowsAtCompileTime),
InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime)
: int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime)
: int(Derived::MaxRowsAtCompileTime),
MaxSizeAtCompileTime = Derived::SizeAtCompileTime,
PacketSize = packet_traits<typename Derived::Scalar>::size
InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime)
: int(DstFlags)&RowMajorBit ? int(Dst::ColsAtCompileTime)
: int(Dst::RowsAtCompileTime),
InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
: int(DstFlags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
: int(Dst::MaxRowsAtCompileTime),
MaxSizeAtCompileTime = Dst::SizeAtCompileTime,
PacketSize = packet_traits<typename Dst::Scalar>::size
};
enum {
StorageOrdersAgree = (int(Derived::IsRowMajor) == int(OtherDerived::IsRowMajor)),
StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)),
MightVectorize = StorageOrdersAgree
&& (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit)
&& (int(DstFlags) & int(SrcFlags) & ActualPacketAccessBit)
&& (functor_traits<AssignFunc>::PacketAccess),
MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
&& int(DstIsAligned) && int(SrcIsAligned),
MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
MayLinearize = StorageOrdersAgree && (int(DstFlags) & int(SrcFlags) & LinearAccessBit),
MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess
&& (DstIsAligned || MaxSizeAtCompileTime == Dynamic),
/* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
@ -81,12 +89,12 @@ public:
private:
enum {
UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1),
MayUnrollCompletely = int(Derived::SizeAtCompileTime) != Dynamic
&& int(OtherDerived::CoeffReadCost) != Dynamic
&& int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
MayUnrollCompletely = int(Dst::SizeAtCompileTime) != Dynamic
&& int(SrcEvaluator::CoeffReadCost) != Dynamic
&& int(Dst::SizeAtCompileTime) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit),
MayUnrollInner = int(InnerSize) != Dynamic
&& int(OtherDerived::CoeffReadCost) != Dynamic
&& int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
&& int(SrcEvaluator::CoeffReadCost) != Dynamic
&& int(InnerSize) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit)
};
public:
@ -518,12 +526,16 @@ public:
typedef SrcEvaluatorTypeT SrcEvaluatorType;
typedef typename DstEvaluatorType::Scalar Scalar;
typedef typename DstEvaluatorType::Index Index;
typedef copy_using_evaluator_traits<DstXprType, SrcXprType, Functor> AssignmentTraits;
typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor> AssignmentTraits;
generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
: m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr)
{}
{
#ifdef EIGEN_DEBUG_ASSIGN
AssignmentTraits::debug();
#endif
}
Index size() const { return m_dstExpr.size(); }
Index innerSize() const { return m_dstExpr.innerSize(); }
@ -612,10 +624,6 @@ protected:
template<typename DstXprType, typename SrcXprType, typename Functor>
void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
{
#ifdef EIGEN_DEBUG_ASSIGN
// TODO these traits should be computed from information provided by the evaluators
internal::copy_using_evaluator_traits<DstXprType, SrcXprType, Functor>::debug();
#endif
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
@ -750,10 +758,6 @@ struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Scalar>
{
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
#ifdef EIGEN_DEBUG_ASSIGN
internal::copy_using_evaluator_traits<DstXprType, SrcXprType, Functor>::debug();
#endif
call_dense_assignment_loop(dst, src, func);
}
};

View File

@ -94,14 +94,14 @@ struct any_unroller<Derived, Dynamic>
template<typename Derived>
inline bool DenseBase<Derived>::all() const
{
enum {
unroll = SizeAtCompileTime != Dynamic
&& CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
#ifdef EIGEN_TEST_EVALUATORS
typedef typename internal::evaluator<Derived>::type Evaluator;
enum {
unroll = SizeAtCompileTime != Dynamic
&& Evaluator::CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
Evaluator evaluator(derived());
if(unroll)
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
@ -113,6 +113,13 @@ inline bool DenseBase<Derived>::all() const
return true;
}
#else
enum {
unroll = SizeAtCompileTime != Dynamic
&& CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
if(unroll)
return internal::all_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived());
else
@ -132,14 +139,14 @@ inline bool DenseBase<Derived>::all() const
template<typename Derived>
inline bool DenseBase<Derived>::any() const
{
enum {
unroll = SizeAtCompileTime != Dynamic
&& CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
#ifdef EIGEN_TEST_EVALUATORS
typedef typename internal::evaluator<Derived>::type Evaluator;
enum {
unroll = SizeAtCompileTime != Dynamic
&& Evaluator::CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
Evaluator evaluator(derived());
if(unroll)
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
@ -151,6 +158,12 @@ inline bool DenseBase<Derived>::any() const
return false;
}
#else
enum {
unroll = SizeAtCompileTime != Dynamic
&& CoeffReadCost != Dynamic
&& NumTraits<Scalar>::AddCost != Dynamic
&& SizeAtCompileTime * (CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
};
if(unroll)
return internal::any_unroller<Derived, unroll ? int(SizeAtCompileTime) : Dynamic>::run(derived());
else

View File

@ -71,7 +71,7 @@ struct evaluator_traits_base
// typedef evaluator<T> type;
// typedef evaluator<T> nestedType;
// by default, get evalautor kind and shape from storage
// by default, get evaluator 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;
@ -124,12 +124,19 @@ struct evaluator<PlainObjectBase<Derived> >
: evaluator_base<Derived>
{
typedef PlainObjectBase<Derived> PlainObjectType;
typedef typename PlainObjectType::Index Index;
typedef typename PlainObjectType::Scalar Scalar;
typedef typename PlainObjectType::CoeffReturnType CoeffReturnType;
typedef typename PlainObjectType::PacketScalar PacketScalar;
typedef typename PlainObjectType::PacketReturnType PacketReturnType;
enum {
IsRowMajor = PlainObjectType::IsRowMajor,
IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime,
RowsAtCompileTime = PlainObjectType::RowsAtCompileTime,
ColsAtCompileTime = PlainObjectType::ColsAtCompileTime
ColsAtCompileTime = PlainObjectType::ColsAtCompileTime,
CoeffReadCost = NumTraits<Scalar>::ReadCost
};
evaluator()
@ -143,12 +150,6 @@ struct evaluator<PlainObjectBase<Derived> >
: m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride())
{ }
typedef typename PlainObjectType::Index Index;
typedef typename PlainObjectType::Scalar Scalar;
typedef typename PlainObjectType::CoeffReturnType CoeffReturnType;
typedef typename PlainObjectType::PacketScalar PacketScalar;
typedef typename PlainObjectType::PacketReturnType PacketReturnType;
CoeffReturnType coeff(Index row, Index col) const
{
if (IsRowMajor)
@ -320,6 +321,10 @@ struct evaluator<Transpose<ArgType> >
: evaluator_base<Transpose<ArgType> >
{
typedef Transpose<ArgType> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost
};
evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
@ -384,6 +389,10 @@ struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
: evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> >
{
typedef CwiseNullaryOp<NullaryOp,PlainObjectType> XprType;
enum {
CoeffReadCost = internal::functor_traits<NullaryOp>::Cost
};
evaluator(const XprType& n)
: m_functor(n.functor())
@ -426,6 +435,10 @@ struct evaluator<CwiseUnaryOp<UnaryOp, ArgType> >
: evaluator_base<CwiseUnaryOp<UnaryOp, ArgType> >
{
typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost
};
evaluator(const XprType& op)
: m_functor(op.functor()),
@ -470,6 +483,10 @@ struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
: evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
enum {
CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost
};
evaluator(const XprType& xpr)
: m_functor(xpr.functor()),
@ -518,6 +535,10 @@ struct evaluator<CwiseUnaryView<UnaryOp, ArgType> >
: evaluator_base<CwiseUnaryView<UnaryOp, ArgType> >
{
typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost
};
evaluator(const XprType& op)
: m_unaryOp(op.functor()),
@ -561,7 +582,6 @@ struct evaluator<MapBase<Derived, AccessorsType> >
{
typedef MapBase<Derived, AccessorsType> MapType;
typedef Derived XprType;
typedef typename XprType::PointerType PointerType;
typedef typename XprType::Index Index;
typedef typename XprType::Scalar Scalar;
@ -569,16 +589,17 @@ struct evaluator<MapBase<Derived, AccessorsType> >
typedef typename XprType::PacketScalar PacketScalar;
typedef typename XprType::PacketReturnType PacketReturnType;
enum {
RowsAtCompileTime = XprType::RowsAtCompileTime,
CoeffReadCost = NumTraits<Scalar>::ReadCost
};
evaluator(const XprType& map)
: m_data(const_cast<PointerType>(map.data())),
m_rowStride(map.rowStride()),
m_colStride(map.colStride())
{ }
enum {
RowsAtCompileTime = XprType::RowsAtCompileTime
};
CoeffReturnType coeff(Index row, Index col) const
{
return m_data[col * m_colStride + row * m_rowStride];
@ -670,6 +691,9 @@ struct evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
: block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel>
{
typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost
};
typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> block_evaluator_type;
evaluator(const XprType& block) : block_evaluator_type(block) {}
};
@ -703,8 +727,7 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAcc
CoeffReturnType coeff(Index index) const
{
return coeff(RowsAtCompileTime == 1 ? 0 : index,
RowsAtCompileTime == 1 ? index : 0);
return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
}
Scalar& coeffRef(Index row, Index col)
@ -714,8 +737,7 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAcc
Scalar& coeffRef(Index index)
{
return coeffRef(RowsAtCompileTime == 1 ? 0 : index,
RowsAtCompileTime == 1 ? index : 0);
return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
}
template<int LoadMode>
@ -728,7 +750,7 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAcc
PacketReturnType packet(Index index) const
{
return packet<LoadMode>(RowsAtCompileTime == 1 ? 0 : index,
RowsAtCompileTime == 1 ? index : 0);
RowsAtCompileTime == 1 ? index : 0);
}
template<int StoreMode>
@ -741,8 +763,8 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAcc
void writePacket(Index index, const PacketScalar& x)
{
return writePacket<StoreMode>(RowsAtCompileTime == 1 ? 0 : index,
RowsAtCompileTime == 1 ? index : 0,
x);
RowsAtCompileTime == 1 ? index : 0,
x);
}
protected:
@ -773,6 +795,11 @@ struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
: evaluator_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
{
typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
enum {
CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost
+ EIGEN_SIZE_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
evaluator<ElseMatrixType>::CoeffReadCost)
};
evaluator(const XprType& select)
: m_conditionImpl(select.conditionMatrix()),
@ -813,6 +840,18 @@ struct evaluator<Replicate<ArgType, RowFactor, ColFactor> >
: evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
{
typedef Replicate<ArgType, RowFactor, ColFactor> XprType;
typedef typename XprType::Index Index;
typedef typename XprType::CoeffReturnType CoeffReturnType;
typedef typename XprType::PacketReturnType PacketReturnType;
enum {
Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor
};
typedef typename internal::nested_eval<ArgType,Factor>::type ArgTypeNested;
typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
enum {
CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost
};
evaluator(const XprType& replicate)
: m_arg(replicate.nestedExpression()),
@ -821,10 +860,6 @@ struct evaluator<Replicate<ArgType, RowFactor, ColFactor> >
m_cols(replicate.nestedExpression().cols())
{ }
typedef typename XprType::Index Index;
typedef typename XprType::CoeffReturnType CoeffReturnType;
typedef typename XprType::PacketReturnType PacketReturnType;
CoeffReturnType coeff(Index row, Index col) const
{
// try to avoid using modulo; this is a pure optimization strategy
@ -852,13 +887,7 @@ struct evaluator<Replicate<ArgType, RowFactor, ColFactor> >
}
protected:
enum {
Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor
};
typedef typename internal::nested_eval<ArgType,Factor>::type ArgTypeNested;
typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
const ArgTypeNested m_arg; // FIXME is it OK to store both the argument and its evaluator?? (we have the same situation in evalautor_product)
const ArgTypeNested m_arg; // FIXME is it OK to store both the argument and its evaluator?? (we have the same situation in evaluator_product)
typename evaluator<ArgTypeNestedCleaned>::nestedType m_argImpl;
const variable_if_dynamic<Index, ArgType::RowsAtCompileTime> m_rows;
const variable_if_dynamic<Index, ArgType::ColsAtCompileTime> m_cols;
@ -876,6 +905,15 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
: evaluator_base<PartialReduxExpr<ArgType, MemberOp, Direction> >
{
typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType;
typedef typename XprType::Scalar InputScalar;
enum {
TraversalSize = Direction==Vertical ? XprType::RowsAtCompileTime : XprType::ColsAtCompileTime
};
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
enum {
CoeffReadCost = TraversalSize==Dynamic ? Dynamic
: TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value)
};
evaluator(const XprType expr)
: m_expr(expr)
@ -909,6 +947,9 @@ struct evaluator_wrapper_base
: evaluator_base<XprType>
{
typedef typename remove_all<typename XprType::NestedExpressionType>::type ArgType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost
};
evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {}
@ -1015,7 +1056,9 @@ struct evaluator<Reverse<ArgType, Direction> >
OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1,
ReversePacket = (Direction == BothDirections)
|| ((Direction == Vertical) && IsColMajor)
|| ((Direction == Horizontal) && IsRowMajor)
|| ((Direction == Horizontal) && IsRowMajor),
CoeffReadCost = evaluator<ArgType>::CoeffReadCost
};
typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet;
@ -1093,6 +1136,10 @@ struct evaluator<Diagonal<ArgType, DiagIndex> >
: evaluator_base<Diagonal<ArgType, DiagIndex> >
{
typedef Diagonal<ArgType, DiagIndex> XprType;
enum {
CoeffReadCost = evaluator<ArgType>::CoeffReadCost
};
evaluator(const XprType& diagonal)
: m_argImpl(diagonal.nestedExpression()),

View File

@ -65,8 +65,6 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
typedef typename remove_reference<LhsNested>::type _LhsNested;
typedef typename remove_reference<RhsNested>::type _RhsNested;
enum {
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
LhsFlags = _LhsNested::Flags,
RhsFlags = _RhsNested::Flags,
SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
@ -80,8 +78,13 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
)
)
),
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit)
#ifndef EIGEN_TEST_EVALUATORS
,
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost
#endif
};
};
} // end namespace internal

View File

@ -39,8 +39,11 @@ struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectT
& ( HereditaryBits
| (functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
| (functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0)))
| (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
| (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit)
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = functor_traits<NullaryOp>::Cost
#endif
};
};
}

View File

@ -46,8 +46,11 @@ struct traits<CwiseUnaryOp<UnaryOp, XprType> >
enum {
Flags = _XprTypeNested::Flags & (
HereditaryBits | LinearAccessBit | AlignedBit
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0))
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits<UnaryOp>::Cost
#endif
};
};
}

View File

@ -38,7 +38,9 @@ struct traits<CwiseUnaryView<ViewOp, MatrixType> >
typedef typename remove_all<MatrixTypeNested>::type _MatrixTypeNested;
enum {
Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)),
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits<ViewOp>::Cost,
#endif
MatrixTypeInnerStride = inner_stride_at_compile_time<MatrixType>::ret,
// need to cast the sizeof's from size_t to int explicitly, otherwise:
// "error: no integral type can represent all of the enumerator values

View File

@ -169,10 +169,12 @@ template<typename Derived> class DenseBase
InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime)
: int(IsRowMajor) ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
/**< This is a rough measure of how expensive it is to read one coefficient from
* this expression.
*/
#endif
InnerStrideAtCompileTime = internal::inner_stride_at_compile_time<Derived>::ret,
OuterStrideAtCompileTime = internal::outer_stride_at_compile_time<Derived>::ret

View File

@ -53,7 +53,9 @@ struct traits<Diagonal<MatrixType,DiagIndex> >
MaxColsAtCompileTime = 1,
MaskLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0,
Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit,
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = _MatrixTypeNested::CoeffReadCost,
#endif
MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret,
InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1,
OuterStrideAtCompileTime = 0

View File

@ -280,8 +280,11 @@ struct traits<DiagonalWrapper<_DiagonalVectorType> >
ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime,
Flags = traits<DiagonalVectorType>::Flags & LvalueBit,
Flags = traits<DiagonalVectorType>::Flags & LvalueBit
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = traits<_DiagonalVectorType>::CoeffReadCost
#endif
};
};
}

View File

@ -35,8 +35,11 @@ struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> >
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && (_ScalarAccessOnDiag || (bool(int(DiagonalType::DiagonalVectorType::Flags)&PacketAccessBit))),
_LinearAccessMask = (RowsAtCompileTime==1 || ColsAtCompileTime==1) ? LinearAccessBit : 0,
Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit,//(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
Flags = ((HereditaryBits|_LinearAccessMask) & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0) | AlignedBit //(int(MatrixType::Flags)&int(DiagonalType::DiagonalVectorType::Flags)&AlignedBit),
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost
#endif
};
};
}

View File

@ -115,7 +115,9 @@ struct traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
MaxRowsAtCompileTime = _MaxRows,
MaxColsAtCompileTime = _MaxCols,
Flags = compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret,
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = NumTraits<Scalar>::ReadCost,
#endif
Options = _Options,
InnerStrideAtCompileTime = 1,
OuterStrideAtCompileTime = (Options&RowMajor) ? ColsAtCompileTime : RowsAtCompileTime

View File

@ -66,8 +66,10 @@ template<typename Derived> class MatrixBase
using Base::MaxSizeAtCompileTime;
using Base::IsVectorAtCompileTime;
using Base::Flags;
#ifndef EIGEN_TEST_EVALUATORS
using Base::CoeffReadCost;
#endif
using Base::derived;
using Base::const_cast_derived;
using Base::rows;

View File

@ -109,6 +109,9 @@ struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, DenseSha
: public evaluator<typename Product<Lhs, Rhs, DefaultProduct>::PlainObject>::type
{
typedef Product<Lhs, Rhs, DefaultProduct> XprType;
// enum {
// CoeffReadCost = 0 // FIXME why is it needed? (this was already the case before the evaluators, see traits<ProductBase>)
// };
typedef typename XprType::PlainObject PlainObject;
typedef typename evaluator<PlainObject>::type Base;
@ -366,6 +369,11 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
{
typedef Product<Lhs, Rhs, LazyProduct> XprType;
typedef CoeffBasedProduct<Lhs, Rhs, 0> CoeffBasedProductType;
typedef typename XprType::Index Index;
typedef typename XprType::Scalar Scalar;
typedef typename XprType::CoeffReturnType CoeffReturnType;
typedef typename XprType::PacketScalar PacketScalar;
typedef typename XprType::PacketReturnType PacketReturnType;
product_evaluator(const XprType& xpr)
: m_lhs(xpr.lhs()),
@ -376,24 +384,8 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
m_innerDim(xpr.lhs().cols())
{ }
typedef typename XprType::Index Index;
typedef typename XprType::Scalar Scalar;
typedef typename XprType::CoeffReturnType CoeffReturnType;
typedef typename XprType::PacketScalar PacketScalar;
typedef typename XprType::PacketReturnType PacketReturnType;
// Everything below here is taken from CoeffBasedProduct.h
enum {
RowsAtCompileTime = traits<CoeffBasedProductType>::RowsAtCompileTime,
PacketSize = packet_traits<Scalar>::size,
InnerSize = traits<CoeffBasedProductType>::InnerSize,
CoeffReadCost = traits<CoeffBasedProductType>::CoeffReadCost,
Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
CanVectorizeInner = traits<CoeffBasedProductType>::CanVectorizeInner,
Flags = traits<CoeffBasedProductType>::Flags
};
typedef typename internal::nested_eval<Lhs,Rhs::ColsAtCompileTime>::type LhsNested;
typedef typename internal::nested_eval<Rhs,Lhs::RowsAtCompileTime>::type RhsNested;
@ -403,6 +395,22 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
typedef typename evaluator<LhsNestedCleaned>::type LhsEtorType;
typedef typename evaluator<RhsNestedCleaned>::type RhsEtorType;
enum {
RowsAtCompileTime = traits<CoeffBasedProductType>::RowsAtCompileTime,
PacketSize = packet_traits<Scalar>::size,
InnerSize = traits<CoeffBasedProductType>::InnerSize,
LhsCoeffReadCost = LhsEtorType::CoeffReadCost,
RhsCoeffReadCost = RhsEtorType::CoeffReadCost,
CoeffReadCost = (InnerSize == Dynamic || LhsCoeffReadCost==Dynamic || RhsCoeffReadCost==Dynamic || NumTraits<Scalar>::AddCost==Dynamic || NumTraits<Scalar>::MulCost==Dynamic) ? Dynamic
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
CanVectorizeInner = traits<CoeffBasedProductType>::CanVectorizeInner,
Flags = traits<CoeffBasedProductType>::Flags
};
const CoeffReturnType coeff(Index row, Index col) const
{
// TODO check performance regression wrt to Eigen 3.2 which has special handling of this function
@ -689,6 +697,10 @@ struct diagonal_product_evaluator_base
typedef typename scalar_product_traits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar;
typedef typename internal::packet_traits<Scalar>::type PacketScalar;
public:
enum {
CoeffReadCost = NumTraits<Scalar>::MulCost + evaluator<MatrixType>::CoeffReadCost + evaluator<DiagonalType>::CoeffReadCost
};
diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag)
: m_diagImpl(diag), m_matImpl(mat)
{
@ -739,7 +751,9 @@ struct product_evaluator<Product<Lhs, Rhs, ProductKind>, ProductTag, DiagonalSha
typedef Product<Lhs, Rhs, ProductKind> XprType;
typedef typename XprType::PlainObject PlainObject;
enum { StorageOrder = int(Rhs::Flags) & RowMajorBit ? RowMajor : ColMajor };
enum {
StorageOrder = int(Rhs::Flags) & RowMajorBit ? RowMajor : ColMajor
};
product_evaluator(const XprType& xpr)
: Base(xpr.rhs(), xpr.lhs().diagonal())

View File

@ -331,7 +331,7 @@ public:
IsRowMajor = XprType::IsRowMajor,
SizeAtCompileTime = XprType::SizeAtCompileTime,
InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime,
CoeffReadCost = XprType::CoeffReadCost
CoeffReadCost = evaluator<XprType>::CoeffReadCost
};
Index rows() const { return m_xpr.rows(); }

View File

@ -53,8 +53,11 @@ struct traits<Replicate<MatrixType,RowFactor,ColFactor> >
IsRowMajor = MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1 ? 1
: MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1 ? 0
: (MatrixType::Flags & RowMajorBit) ? 1 : 0,
Flags = (_MatrixTypeNested::Flags & HereditaryBits & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0),
Flags = (_MatrixTypeNested::Flags & HereditaryBits & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0)
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
#endif
};
};
}

View File

@ -49,9 +49,11 @@ struct traits<Reverse<MatrixType, Direction> >
LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) )
? LinearAccessBit : 0,
Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess),
Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess)
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
#endif
};
};

View File

@ -43,10 +43,13 @@ struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits,
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = traits<typename remove_all<ConditionMatrixNested>::type>::CoeffReadCost
+ EIGEN_SIZE_MAX(traits<typename remove_all<ThenMatrixNested>::type>::CoeffReadCost,
traits<typename remove_all<ElseMatrixNested>::type>::CoeffReadCost)
#endif
};
};
}

View File

@ -45,7 +45,9 @@ struct traits<Transpose<MatrixType> > : traits<MatrixType>
Flags0 = MatrixTypeNestedPlain::Flags & ~(LvalueBit | NestByRefBit),
Flags1 = Flags0 | FlagsLvalueBit,
Flags = Flags1 ^ RowMajorBit,
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = MatrixTypeNestedPlain::CoeffReadCost,
#endif
InnerStrideAtCompileTime = inner_stride_at_compile_time<MatrixType>::ret,
OuterStrideAtCompileTime = outer_stride_at_compile_time<MatrixType>::ret
};

View File

@ -32,7 +32,9 @@ template<typename Derived> class TriangularBase : public EigenBase<Derived>
enum {
Mode = internal::traits<Derived>::Mode,
#ifndef EIGEN_TEST_EVALUATORS
CoeffReadCost = internal::traits<Derived>::CoeffReadCost,
#endif
RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
@ -174,8 +176,11 @@ struct traits<TriangularView<MatrixType, _Mode> > : traits<MatrixType>
typedef typename MatrixType::PlainObject DenseMatrixType;
enum {
Mode = _Mode,
Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | LvalueBit) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode,
Flags = (MatrixTypeNestedCleaned::Flags & (HereditaryBits | LvalueBit) & (~(PacketAccessBit | DirectAccessBit | LinearAccessBit))) | Mode
#ifndef EIGEN_TEST_EVALUATORS
,
CoeffReadCost = MatrixTypeNestedCleaned::CoeffReadCost
#endif
};
};
}
@ -1141,10 +1146,6 @@ public:
template<int Mode, bool SetOpposite, typename DstXprType, typename SrcXprType, typename Functor>
void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
{
#ifdef EIGEN_DEBUG_ASSIGN
// TODO these traits should be computed from information provided by the evaluators
internal::copy_using_evaluator_traits<DstXprType, SrcXprType>::debug();
#endif
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
typedef typename evaluator<DstXprType>::type DstEvaluatorType;
@ -1159,8 +1160,8 @@ void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& sr
enum {
unroll = DstXprType::SizeAtCompileTime != Dynamic
&& internal::traits<SrcXprType>::CoeffReadCost != Dynamic
&& DstXprType::SizeAtCompileTime * internal::traits<SrcXprType>::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT
&& SrcEvaluatorType::CoeffReadCost != Dynamic
&& DstXprType::SizeAtCompileTime * SrcEvaluatorType::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT
};
triangular_assignment_loop<Kernel, Mode, unroll ? int(DstXprType::SizeAtCompileTime) : Dynamic, SetOpposite>::run(kernel);

View File

@ -52,6 +52,7 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
Flags = (Flags0 & ~RowMajorBit) | (RowsAtCompileTime == 1 ? RowMajorBit : 0),
TraversalSize = Direction==Vertical ? MatrixType::RowsAtCompileTime : MatrixType::ColsAtCompileTime
};
#ifndef EIGEN_TEST_EVALUATORS
#if EIGEN_GNUC_AT_LEAST(3,4)
typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
#else
@ -61,6 +62,7 @@ struct traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
CoeffReadCost = TraversalSize==Dynamic ? Dynamic
: TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value)
};
#endif
};
}

View File

@ -53,6 +53,35 @@ struct visitor_impl<Visitor, Derived, Dynamic>
}
};
#ifdef EIGEN_ENABLE_EVALUATORS
// evaluator adaptor
template<typename XprType>
class visitor_evaluator
{
public:
visitor_evaluator(const XprType &xpr) : m_evaluator(xpr), m_xpr(xpr) {}
typedef typename XprType::Index Index;
typedef typename XprType::Scalar Scalar;
typedef typename XprType::CoeffReturnType CoeffReturnType;
enum {
RowsAtCompileTime = XprType::RowsAtCompileTime,
CoeffReadCost = internal::evaluator<XprType>::CoeffReadCost
};
Index rows() const { return m_xpr.rows(); }
Index cols() const { return m_xpr.cols(); }
Index size() const { return m_xpr.size(); }
CoeffReturnType coeff(Index row, Index col) const
{ return m_evaluator.coeff(row, col); }
protected:
typename internal::evaluator<XprType>::nestedType m_evaluator;
const XprType &m_xpr;
};
#endif
} // end namespace internal
/** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
@ -76,6 +105,19 @@ template<typename Derived>
template<typename Visitor>
void DenseBase<Derived>::visit(Visitor& visitor) const
{
#ifdef EIGEN_TEST_EVALUATORS
typedef typename internal::visitor_evaluator<Derived> ThisEvaluator;
ThisEvaluator thisEval(derived());
enum { unroll = SizeAtCompileTime != Dynamic
&& ThisEvaluator::CoeffReadCost != Dynamic
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
&& SizeAtCompileTime * ThisEvaluator::CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
<= EIGEN_UNROLLING_LIMIT };
return internal::visitor_impl<Visitor, ThisEvaluator,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(thisEval, visitor);
#else
enum { unroll = SizeAtCompileTime != Dynamic
&& CoeffReadCost != Dynamic
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
@ -84,6 +126,7 @@ void DenseBase<Derived>::visit(Visitor& visitor) const
return internal::visitor_impl<Visitor, Derived,
unroll ? int(SizeAtCompileTime) : Dynamic
>::run(derived(), visitor);
#endif
}
namespace internal {

View File

@ -47,8 +47,6 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
typename traits<_RhsNested>::Index>::type Index;
enum {
LhsCoeffReadCost = traits<_LhsNested>::CoeffReadCost,
RhsCoeffReadCost = traits<_RhsNested>::CoeffReadCost,
LhsFlags = traits<_LhsNested>::Flags,
RhsFlags = traits<_RhsNested>::Flags,
@ -89,11 +87,13 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
| (CanVectorizeRhs ? (RhsFlags & AlignedBit) : 0)
// TODO enable vectorization for mixed types
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
#ifndef EIGEN_TEST_EVALUATORS
LhsCoeffReadCost = traits<_LhsNested>::CoeffReadCost,
RhsCoeffReadCost = traits<_RhsNested>::CoeffReadCost,
CoeffReadCost = (InnerSize == Dynamic || LhsCoeffReadCost==Dynamic || RhsCoeffReadCost==Dynamic || NumTraits<Scalar>::AddCost==Dynamic || NumTraits<Scalar>::MulCost==Dynamic) ? Dynamic
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
#endif
/* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
* of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner
* loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect

View File

@ -345,6 +345,8 @@
* documentation in a single line.
**/
#ifndef EIGEN_TEST_EVALUATORS
#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived) \
typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
@ -381,7 +383,46 @@
using Base::derived; \
using Base::const_cast_derived;
#else
// TODO The EIGEN_DENSE_PUBLIC_INTERFACE should not exists anymore
#define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived) \
typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief The return type for coefficient access. \details Depending on whether the object allows direct coefficient access (e.g. for a MatrixXd), this type is either 'const Scalar&' or simply 'Scalar' for objects that do not allow direct coefficient access. */ \
typedef typename Eigen::internal::nested<Derived>::type Nested; \
typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
typedef typename Eigen::internal::traits<Derived>::Index Index; \
enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
Flags = Eigen::internal::traits<Derived>::Flags, \
SizeAtCompileTime = Base::SizeAtCompileTime, \
MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
IsVectorAtCompileTime = Base::IsVectorAtCompileTime };
#define EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \
typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex<float>. */ \
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex<T>, T were corresponding to RealScalar. */ \
typedef typename Base::PacketScalar PacketScalar; \
typedef typename Base::CoeffReturnType CoeffReturnType; /*!< \brief The return type for coefficient access. \details Depending on whether the object allows direct coefficient access (e.g. for a MatrixXd), this type is either 'const Scalar&' or simply 'Scalar' for objects that do not allow direct coefficient access. */ \
typedef typename Eigen::internal::nested<Derived>::type Nested; \
typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \
typedef typename Eigen::internal::traits<Derived>::Index Index; \
enum { RowsAtCompileTime = Eigen::internal::traits<Derived>::RowsAtCompileTime, \
ColsAtCompileTime = Eigen::internal::traits<Derived>::ColsAtCompileTime, \
MaxRowsAtCompileTime = Eigen::internal::traits<Derived>::MaxRowsAtCompileTime, \
MaxColsAtCompileTime = Eigen::internal::traits<Derived>::MaxColsAtCompileTime, \
Flags = Eigen::internal::traits<Derived>::Flags, \
SizeAtCompileTime = Base::SizeAtCompileTime, \
MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \
IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; \
using Base::derived; \
using Base::const_cast_derived;
#endif // EIGEN_TEST_EVALUATORS
#define EIGEN_PLAIN_ENUM_MIN(a,b) (((int)a <= (int)b) ? (int)a : (int)b)
#define EIGEN_PLAIN_ENUM_MAX(a,b) (((int)a >= (int)b) ? (int)a : (int)b)

View File

@ -370,7 +370,9 @@ template<typename T, int n, typename PlainObject = typename eval<T>::type> struc
DynamicAsInteger = 10000,
ScalarReadCost = NumTraits<typename traits<T>::Scalar>::ReadCost,
ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost),
CoeffReadCost = traits<T>::CoeffReadCost,
CoeffReadCost = evaluator<T>::CoeffReadCost, // TODO What if an evaluator evaluate itself into a tempory?
// Then CoeffReadCost will be small but we still have to evaluate if n>1...
// The solution might be to ask the evaluator if it creates a temp. Perhaps we could even ask the number of temps?
CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost),
NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n,
CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger,