diff --git a/Eigen/src/Core/ArrayBase.h b/Eigen/src/Core/ArrayBase.h index e67ca34cd..d1c422836 100644 --- a/Eigen/src/Core/ArrayBase.h +++ b/Eigen/src/Core/ArrayBase.h @@ -64,8 +64,10 @@ template 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; diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 95306a9a7..95eb37dd5 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -508,9 +508,6 @@ EIGEN_STRONG_INLINE Derived& DenseBase #ifdef EIGEN_TEST_EVALUATORS -#ifdef EIGEN_DEBUG_ASSIGN - internal::copy_using_evaluator_traits::debug(); -#endif eigen_assert(rows() == other.rows() && cols() == other.cols()); internal::call_dense_assignment_loop(derived(),other.derived()); diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 14effd1f2..2ea1cc126 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -24,37 +24,45 @@ namespace internal { // copy_using_evaluator_traits is based on assign_traits -template +template 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::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::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::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 AssignmentTraits; + typedef copy_using_evaluator_traits 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 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::debug(); -#endif eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); typedef typename evaluator::type DstEvaluatorType; @@ -750,10 +758,6 @@ struct Assignment { eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); - #ifdef EIGEN_DEBUG_ASSIGN - internal::copy_using_evaluator_traits::debug(); - #endif - call_dense_assignment_loop(dst, src, func); } }; diff --git a/Eigen/src/Core/BooleanRedux.h b/Eigen/src/Core/BooleanRedux.h index f0b68f470..192e1db53 100644 --- a/Eigen/src/Core/BooleanRedux.h +++ b/Eigen/src/Core/BooleanRedux.h @@ -94,14 +94,14 @@ struct any_unroller template inline bool DenseBase::all() const { - enum { - unroll = SizeAtCompileTime != Dynamic - && CoeffReadCost != Dynamic - && NumTraits::AddCost != Dynamic - && SizeAtCompileTime * (CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT - }; #ifdef EIGEN_TEST_EVALUATORS typedef typename internal::evaluator::type Evaluator; + enum { + unroll = SizeAtCompileTime != Dynamic + && Evaluator::CoeffReadCost != Dynamic + && NumTraits::AddCost != Dynamic + && SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT + }; Evaluator evaluator(derived()); if(unroll) return internal::all_unroller::run(evaluator); @@ -113,6 +113,13 @@ inline bool DenseBase::all() const return true; } #else + enum { + unroll = SizeAtCompileTime != Dynamic + && CoeffReadCost != Dynamic + && NumTraits::AddCost != Dynamic + && SizeAtCompileTime * (CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT + }; + if(unroll) return internal::all_unroller::run(derived()); else @@ -132,14 +139,14 @@ inline bool DenseBase::all() const template inline bool DenseBase::any() const { - enum { - unroll = SizeAtCompileTime != Dynamic - && CoeffReadCost != Dynamic - && NumTraits::AddCost != Dynamic - && SizeAtCompileTime * (CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT - }; #ifdef EIGEN_TEST_EVALUATORS typedef typename internal::evaluator::type Evaluator; + enum { + unroll = SizeAtCompileTime != Dynamic + && Evaluator::CoeffReadCost != Dynamic + && NumTraits::AddCost != Dynamic + && SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT + }; Evaluator evaluator(derived()); if(unroll) return internal::any_unroller::run(evaluator); @@ -151,6 +158,12 @@ inline bool DenseBase::any() const return false; } #else + enum { + unroll = SizeAtCompileTime != Dynamic + && CoeffReadCost != Dynamic + && NumTraits::AddCost != Dynamic + && SizeAtCompileTime * (CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT + }; if(unroll) return internal::any_unroller::run(derived()); else diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index 92b50d190..33c89c2d4 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -71,7 +71,7 @@ struct evaluator_traits_base // typedef evaluator type; // typedef evaluator 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::Kind Kind; typedef typename storage_kind_to_shape::Shape Shape; @@ -124,12 +124,19 @@ struct evaluator > : evaluator_base { typedef PlainObjectBase 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::ReadCost }; evaluator() @@ -143,12 +150,6 @@ struct evaluator > : 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 > : evaluator_base > { typedef Transpose XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + }; evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {} @@ -384,6 +389,10 @@ struct evaluator > : evaluator_base > { typedef CwiseNullaryOp XprType; + + enum { + CoeffReadCost = internal::functor_traits::Cost + }; evaluator(const XprType& n) : m_functor(n.functor()) @@ -426,6 +435,10 @@ struct evaluator > : evaluator_base > { typedef CwiseUnaryOp XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + functor_traits::Cost + }; evaluator(const XprType& op) : m_functor(op.functor()), @@ -470,6 +483,10 @@ struct evaluator > : evaluator_base > { typedef CwiseBinaryOp XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + evaluator::CoeffReadCost + functor_traits::Cost + }; evaluator(const XprType& xpr) : m_functor(xpr.functor()), @@ -518,6 +535,10 @@ struct evaluator > : evaluator_base > { typedef CwiseUnaryView XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + functor_traits::Cost + }; evaluator(const XprType& op) : m_unaryOp(op.functor()), @@ -561,7 +582,6 @@ struct evaluator > { typedef MapBase 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 > typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; + enum { + RowsAtCompileTime = XprType::RowsAtCompileTime, + CoeffReadCost = NumTraits::ReadCost + }; + evaluator(const XprType& map) : m_data(const_cast(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_evaluator { typedef Block XprType; + enum { + CoeffReadCost = evaluator::CoeffReadCost + }; typedef block_evaluator block_evaluator_type; evaluator(const XprType& block) : block_evaluator_type(block) {} }; @@ -703,8 +727,7 @@ struct block_evaluator @@ -728,7 +750,7 @@ struct block_evaluator(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0); + RowsAtCompileTime == 1 ? index : 0); } template @@ -741,8 +763,8 @@ struct block_evaluator(RowsAtCompileTime == 1 ? 0 : index, - RowsAtCompileTime == 1 ? index : 0, - x); + RowsAtCompileTime == 1 ? index : 0, + x); } protected: @@ -773,6 +795,11 @@ struct evaluator > : evaluator_base > { typedef Select XprType; + enum { + CoeffReadCost = evaluator::CoeffReadCost + + EIGEN_SIZE_MAX(evaluator::CoeffReadCost, + evaluator::CoeffReadCost) + }; evaluator(const XprType& select) : m_conditionImpl(select.conditionMatrix()), @@ -813,6 +840,18 @@ struct evaluator > : evaluator_base > { typedef Replicate 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::type ArgTypeNested; + typedef typename internal::remove_all::type ArgTypeNestedCleaned; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + }; evaluator(const XprType& replicate) : m_arg(replicate.nestedExpression()), @@ -821,10 +860,6 @@ struct evaluator > 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 > } protected: - enum { - Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor - }; - typedef typename internal::nested_eval::type ArgTypeNested; - typedef typename internal::remove_all::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::nestedType m_argImpl; const variable_if_dynamic m_rows; const variable_if_dynamic m_cols; @@ -876,6 +905,15 @@ struct evaluator > : evaluator_base > { typedef PartialReduxExpr XprType; + typedef typename XprType::Scalar InputScalar; + enum { + TraversalSize = Direction==Vertical ? XprType::RowsAtCompileTime : XprType::ColsAtCompileTime + }; + typedef typename MemberOp::template Cost CostOpType; + enum { + CoeffReadCost = TraversalSize==Dynamic ? Dynamic + : TraversalSize * evaluator::CoeffReadCost + int(CostOpType::value) + }; evaluator(const XprType expr) : m_expr(expr) @@ -909,6 +947,9 @@ struct evaluator_wrapper_base : evaluator_base { typedef typename remove_all::type ArgType; + enum { + CoeffReadCost = evaluator::CoeffReadCost + }; evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {} @@ -1015,7 +1056,9 @@ struct evaluator > OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, ReversePacket = (Direction == BothDirections) || ((Direction == Vertical) && IsColMajor) - || ((Direction == Horizontal) && IsRowMajor) + || ((Direction == Horizontal) && IsRowMajor), + + CoeffReadCost = evaluator::CoeffReadCost }; typedef internal::reverse_packet_cond reverse_packet; @@ -1093,6 +1136,10 @@ struct evaluator > : evaluator_base > { typedef Diagonal XprType; + + enum { + CoeffReadCost = evaluator::CoeffReadCost + }; evaluator(const XprType& diagonal) : m_argImpl(diagonal.nestedExpression()), diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h index c78067a88..105e7fb11 100644 --- a/Eigen/src/Core/CwiseBinaryOp.h +++ b/Eigen/src/Core/CwiseBinaryOp.h @@ -65,8 +65,6 @@ struct traits > typedef typename remove_reference::type _LhsNested; typedef typename remove_reference::type _RhsNested; enum { - LhsCoeffReadCost = _LhsNested::CoeffReadCost, - RhsCoeffReadCost = _RhsNested::CoeffReadCost, LhsFlags = _LhsNested::Flags, RhsFlags = _RhsNested::Flags, SameType = is_same::value, @@ -80,8 +78,13 @@ struct traits > ) ) ), - 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::Cost +#endif }; }; } // end namespace internal diff --git a/Eigen/src/Core/CwiseNullaryOp.h b/Eigen/src/Core/CwiseNullaryOp.h index 124383114..560e03f12 100644 --- a/Eigen/src/Core/CwiseNullaryOp.h +++ b/Eigen/src/Core/CwiseNullaryOp.h @@ -39,8 +39,11 @@ struct traits > : traits::ret ? LinearAccessBit : 0) | (functor_traits::PacketAccess ? PacketAccessBit : 0))) - | (functor_traits::IsRepeatable ? 0 : EvalBeforeNestingBit), + | (functor_traits::IsRepeatable ? 0 : EvalBeforeNestingBit) +#ifndef EIGEN_TEST_EVALUATORS + , CoeffReadCost = functor_traits::Cost +#endif }; }; } diff --git a/Eigen/src/Core/CwiseUnaryOp.h b/Eigen/src/Core/CwiseUnaryOp.h index aa7df197f..25da52ab7 100644 --- a/Eigen/src/Core/CwiseUnaryOp.h +++ b/Eigen/src/Core/CwiseUnaryOp.h @@ -46,8 +46,11 @@ struct traits > enum { Flags = _XprTypeNested::Flags & ( HereditaryBits | LinearAccessBit | AlignedBit - | (functor_traits::PacketAccess ? PacketAccessBit : 0)), + | (functor_traits::PacketAccess ? PacketAccessBit : 0)) +#ifndef EIGEN_TEST_EVALUATORS + , CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits::Cost +#endif }; }; } diff --git a/Eigen/src/Core/CwiseUnaryView.h b/Eigen/src/Core/CwiseUnaryView.h index b2638d326..a0bd80fb9 100644 --- a/Eigen/src/Core/CwiseUnaryView.h +++ b/Eigen/src/Core/CwiseUnaryView.h @@ -38,7 +38,9 @@ struct traits > typedef typename remove_all::type _MatrixTypeNested; enum { Flags = (traits<_MatrixTypeNested>::Flags & (HereditaryBits | LvalueBit | LinearAccessBit | DirectAccessBit)), +#ifndef EIGEN_TEST_EVALUATORS CoeffReadCost = traits<_MatrixTypeNested>::CoeffReadCost + functor_traits::Cost, +#endif MatrixTypeInnerStride = inner_stride_at_compile_time::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 diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 2fea574dd..f3c79aa31 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -169,10 +169,12 @@ template class DenseBase InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime) : int(IsRowMajor) ? int(ColsAtCompileTime) : int(RowsAtCompileTime), +#ifndef EIGEN_TEST_EVALUATORS CoeffReadCost = internal::traits::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::ret, OuterStrideAtCompileTime = internal::outer_stride_at_compile_time::ret diff --git a/Eigen/src/Core/Diagonal.h b/Eigen/src/Core/Diagonal.h index b160479ab..02ab04980 100644 --- a/Eigen/src/Core/Diagonal.h +++ b/Eigen/src/Core/Diagonal.h @@ -53,7 +53,9 @@ struct traits > MaxColsAtCompileTime = 1, MaskLvalueBit = is_lvalue::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::ret, InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1, OuterStrideAtCompileTime = 0 diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 8df636928..784e4b1ce 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -280,8 +280,11 @@ struct traits > ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, - Flags = traits::Flags & LvalueBit, + Flags = traits::Flags & LvalueBit +#ifndef EIGEN_TEST_EVALUATORS + , CoeffReadCost = traits<_DiagonalVectorType>::CoeffReadCost +#endif }; }; } diff --git a/Eigen/src/Core/DiagonalProduct.h b/Eigen/src/Core/DiagonalProduct.h index f5539df13..840b70dbb 100644 --- a/Eigen/src/Core/DiagonalProduct.h +++ b/Eigen/src/Core/DiagonalProduct.h @@ -35,8 +35,11 @@ struct traits > _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::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost +#endif }; }; } diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index c2cedbf6a..f84db0dc2 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -115,7 +115,9 @@ struct traits > MaxRowsAtCompileTime = _MaxRows, MaxColsAtCompileTime = _MaxCols, Flags = compute_matrix_flags<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::ret, +#ifndef EIGEN_TEST_EVALUATORS CoeffReadCost = NumTraits::ReadCost, +#endif Options = _Options, InnerStrideAtCompileTime = 1, OuterStrideAtCompileTime = (Options&RowMajor) ? ColsAtCompileTime : RowsAtCompileTime diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 72aa75da8..1f9f295c9 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -66,8 +66,10 @@ template 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; diff --git a/Eigen/src/Core/ProductEvaluators.h b/Eigen/src/Core/ProductEvaluators.h index b16b86d8f..7ebf31696 100644 --- a/Eigen/src/Core/ProductEvaluators.h +++ b/Eigen/src/Core/ProductEvaluators.h @@ -109,6 +109,9 @@ struct product_evaluator, ProductTag, DenseSha : public evaluator::PlainObject>::type { typedef Product XprType; +// enum { +// CoeffReadCost = 0 // FIXME why is it needed? (this was already the case before the evaluators, see traits) +// }; typedef typename XprType::PlainObject PlainObject; typedef typename evaluator::type Base; @@ -366,6 +369,11 @@ struct product_evaluator, ProductTag, DenseShape, { typedef Product XprType; typedef CoeffBasedProduct 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, 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::RowsAtCompileTime, - PacketSize = packet_traits::size, - InnerSize = traits::InnerSize, - CoeffReadCost = traits::CoeffReadCost, - Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT, - CanVectorizeInner = traits::CanVectorizeInner, - Flags = traits::Flags - }; - typedef typename internal::nested_eval::type LhsNested; typedef typename internal::nested_eval::type RhsNested; @@ -403,6 +395,22 @@ struct product_evaluator, ProductTag, DenseShape, typedef typename evaluator::type LhsEtorType; typedef typename evaluator::type RhsEtorType; + enum { + RowsAtCompileTime = traits::RowsAtCompileTime, + PacketSize = packet_traits::size, + InnerSize = traits::InnerSize, + + LhsCoeffReadCost = LhsEtorType::CoeffReadCost, + RhsCoeffReadCost = RhsEtorType::CoeffReadCost, + CoeffReadCost = (InnerSize == Dynamic || LhsCoeffReadCost==Dynamic || RhsCoeffReadCost==Dynamic || NumTraits::AddCost==Dynamic || NumTraits::MulCost==Dynamic) ? Dynamic + : InnerSize * (NumTraits::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) + + (InnerSize - 1) * NumTraits::AddCost, + + Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT, + CanVectorizeInner = traits::CanVectorizeInner, + Flags = traits::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::ReturnType Scalar; typedef typename internal::packet_traits::type PacketScalar; public: + enum { + CoeffReadCost = NumTraits::MulCost + evaluator::CoeffReadCost + evaluator::CoeffReadCost + }; + diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag) : m_diagImpl(diag), m_matImpl(mat) { @@ -739,7 +751,9 @@ struct product_evaluator, ProductTag, DiagonalSha typedef Product 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()) diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h index 1b6a4177a..41290323f 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -331,7 +331,7 @@ public: IsRowMajor = XprType::IsRowMajor, SizeAtCompileTime = XprType::SizeAtCompileTime, InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime, - CoeffReadCost = XprType::CoeffReadCost + CoeffReadCost = evaluator::CoeffReadCost }; Index rows() const { return m_xpr.rows(); } diff --git a/Eigen/src/Core/Replicate.h b/Eigen/src/Core/Replicate.h index dde86a834..1e640d8aa 100644 --- a/Eigen/src/Core/Replicate.h +++ b/Eigen/src/Core/Replicate.h @@ -53,8 +53,11 @@ struct traits > 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 }; }; } diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h index e30ae3d28..495b44cc4 100644 --- a/Eigen/src/Core/Reverse.h +++ b/Eigen/src/Core/Reverse.h @@ -49,9 +49,11 @@ struct traits > 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 }; }; diff --git a/Eigen/src/Core/Select.h b/Eigen/src/Core/Select.h index 87993bbb5..abcba2d15 100644 --- a/Eigen/src/Core/Select.h +++ b/Eigen/src/Core/Select.h @@ -43,10 +43,13 @@ struct traits > 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::type>::CoeffReadCost + EIGEN_SIZE_MAX(traits::type>::CoeffReadCost, traits::type>::CoeffReadCost) +#endif }; }; } diff --git a/Eigen/src/Core/Transpose.h b/Eigen/src/Core/Transpose.h index 976708a0f..98f9e888f 100644 --- a/Eigen/src/Core/Transpose.h +++ b/Eigen/src/Core/Transpose.h @@ -45,7 +45,9 @@ struct traits > : traits 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::ret, OuterStrideAtCompileTime = outer_stride_at_compile_time::ret }; diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h index 96c81f933..064e0e10d 100644 --- a/Eigen/src/Core/TriangularMatrix.h +++ b/Eigen/src/Core/TriangularMatrix.h @@ -32,7 +32,9 @@ template class TriangularBase : public EigenBase enum { Mode = internal::traits::Mode, +#ifndef EIGEN_TEST_EVALUATORS CoeffReadCost = internal::traits::CoeffReadCost, +#endif RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime, MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, @@ -174,8 +176,11 @@ struct traits > : traits 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 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::debug(); -#endif eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); typedef typename evaluator::type DstEvaluatorType; @@ -1159,8 +1160,8 @@ void call_triangular_assignment_loop(const DstXprType& dst, const SrcXprType& sr enum { unroll = DstXprType::SizeAtCompileTime != Dynamic - && internal::traits::CoeffReadCost != Dynamic - && DstXprType::SizeAtCompileTime * internal::traits::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT + && SrcEvaluatorType::CoeffReadCost != Dynamic + && DstXprType::SizeAtCompileTime * SrcEvaluatorType::CoeffReadCost / 2 <= EIGEN_UNROLLING_LIMIT }; triangular_assignment_loop::run(kernel); diff --git a/Eigen/src/Core/VectorwiseOp.h b/Eigen/src/Core/VectorwiseOp.h index f25ddca17..702d0006d 100644 --- a/Eigen/src/Core/VectorwiseOp.h +++ b/Eigen/src/Core/VectorwiseOp.h @@ -52,6 +52,7 @@ struct traits > 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 CostOpType; #else @@ -61,6 +62,7 @@ struct traits > CoeffReadCost = TraversalSize==Dynamic ? Dynamic : TraversalSize * traits<_MatrixTypeNested>::CoeffReadCost + int(CostOpType::value) }; +#endif }; } diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h index 64867b7a2..fba0e2a76 100644 --- a/Eigen/src/Core/Visitor.h +++ b/Eigen/src/Core/Visitor.h @@ -53,6 +53,35 @@ struct visitor_impl } }; +#ifdef EIGEN_ENABLE_EVALUATORS +// evaluator adaptor +template +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::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::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 template void DenseBase::visit(Visitor& visitor) const { +#ifdef EIGEN_TEST_EVALUATORS + typedef typename internal::visitor_evaluator ThisEvaluator; + ThisEvaluator thisEval(derived()); + + enum { unroll = SizeAtCompileTime != Dynamic + && ThisEvaluator::CoeffReadCost != Dynamic + && (SizeAtCompileTime == 1 || internal::functor_traits::Cost != Dynamic) + && SizeAtCompileTime * ThisEvaluator::CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits::Cost + <= EIGEN_UNROLLING_LIMIT }; + return internal::visitor_impl::run(thisEval, visitor); +#else enum { unroll = SizeAtCompileTime != Dynamic && CoeffReadCost != Dynamic && (SizeAtCompileTime == 1 || internal::functor_traits::Cost != Dynamic) @@ -84,6 +126,7 @@ void DenseBase::visit(Visitor& visitor) const return internal::visitor_impl::run(derived(), visitor); +#endif } namespace internal { diff --git a/Eigen/src/Core/products/CoeffBasedProduct.h b/Eigen/src/Core/products/CoeffBasedProduct.h index 77f291ab9..94099b7d3 100644 --- a/Eigen/src/Core/products/CoeffBasedProduct.h +++ b/Eigen/src/Core/products/CoeffBasedProduct.h @@ -47,8 +47,6 @@ struct traits > 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 > | (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::AddCost==Dynamic || NumTraits::MulCost==Dynamic) ? Dynamic : InnerSize * (NumTraits::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) + (InnerSize - 1) * NumTraits::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 diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index debc04f3f..3a1dec129 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -345,6 +345,8 @@ * documentation in a single line. **/ +#ifndef EIGEN_TEST_EVALUATORS + #define EIGEN_GENERIC_PUBLIC_INTERFACE(Derived) \ typedef typename Eigen::internal::traits::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex. */ \ typedef typename Eigen::NumTraits::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex, 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::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex. */ \ + typedef typename Eigen::NumTraits::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex, 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::type Nested; \ + typedef typename Eigen::internal::traits::StorageKind StorageKind; \ + typedef typename Eigen::internal::traits::Index Index; \ + enum { RowsAtCompileTime = Eigen::internal::traits::RowsAtCompileTime, \ + ColsAtCompileTime = Eigen::internal::traits::ColsAtCompileTime, \ + Flags = Eigen::internal::traits::Flags, \ + SizeAtCompileTime = Base::SizeAtCompileTime, \ + MaxSizeAtCompileTime = Base::MaxSizeAtCompileTime, \ + IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; + + +#define EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \ + typedef typename Eigen::internal::traits::Scalar Scalar; /*!< \brief Numeric type, e.g. float, double, int or std::complex. */ \ + typedef typename Eigen::NumTraits::Real RealScalar; /*!< \brief The underlying numeric type for composed scalar types. \details In cases where Scalar is e.g. std::complex, 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::type Nested; \ + typedef typename Eigen::internal::traits::StorageKind StorageKind; \ + typedef typename Eigen::internal::traits::Index Index; \ + enum { RowsAtCompileTime = Eigen::internal::traits::RowsAtCompileTime, \ + ColsAtCompileTime = Eigen::internal::traits::ColsAtCompileTime, \ + MaxRowsAtCompileTime = Eigen::internal::traits::MaxRowsAtCompileTime, \ + MaxColsAtCompileTime = Eigen::internal::traits::MaxColsAtCompileTime, \ + Flags = Eigen::internal::traits::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) diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index a4baa921c..8931c5a2d 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -370,7 +370,9 @@ template::type> struc DynamicAsInteger = 10000, ScalarReadCost = NumTraits::Scalar>::ReadCost, ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost), - CoeffReadCost = traits::CoeffReadCost, + CoeffReadCost = evaluator::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,