From 8c66b6bc6157da3aaa7a8529e1fcd6e257e7693f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 27 Oct 2015 11:06:42 +0100 Subject: Simplify evaluator::Flags for Map<> --- Eigen/src/Core/CoreEvaluators.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'Eigen/src/Core/CoreEvaluators.h') diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index c0563f534..c898b2abc 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -633,20 +633,9 @@ struct evaluator > HasNoStride = HasNoInnerStride && HasNoOuterStride, IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic, - // FIXME I don't get the code below, in particular why outer-stride-at-compile-time should have any effect on PacketAccessBit... - // Let's remove the code below for 3.4 if no issue occur -// PacketAlignment = unpacket_traits::alignment, -// KeepsPacketAccess = bool(HasNoInnerStride) -// && ( bool(IsDynamicSize) -// || HasNoOuterStride -// || ( OuterStrideAtCompileTime!=Dynamic -// && ((static_cast(sizeof(Scalar))*OuterStrideAtCompileTime) % PacketAlignment)==0 ) ), - KeepsPacketAccess = bool(HasNoInnerStride), - - Flags0 = evaluator::Flags, - Flags1 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime)) - ? int(Flags0) : int(Flags0 & ~LinearAccessBit), - Flags = KeepsPacketAccess ? int(Flags1) : (int(Flags1) & ~PacketAccessBit), + PacketAccessMask = bool(HasNoInnerStride) ? ~int(0) : ~int(PacketAccessBit), + LinearAccessMask = bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime) ? ~int(0) : ~int(LinearAccessBit), + Flags = int( evaluator::Flags) & (LinearAccessMask&PacketAccessMask), Alignment = int(MapOptions)&int(AlignedMask) }; -- cgit v1.2.3 From 77ff3386b7d28c68c9e277e60f285ae1b3124b47 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 28 Oct 2015 11:42:14 +0100 Subject: Refactoring of the cost model: - Dynamic is now an invalid value - introduce a HugeCost constant to be used for runtime-cost values or arbitrarily huge cost - add sanity checks for cost values: must be >=0 and not too large This change provides several benefits: - it fixes shortcoming is some cost computation where the Dynamic case was not properly handled. - it simplifies cost computation logic, and should avoid future similar shortcomings. - it allows to distinguish between different level of dynamic/huge/infinite cost - it should enable further simplifications in the computation of costs (save compilation time) --- Eigen/src/Core/AssignEvaluator.h | 4 +- Eigen/src/Core/BooleanRedux.h | 8 ++-- Eigen/src/Core/CoreEvaluators.h | 50 ++++++++++++++++------ Eigen/src/Core/NumTraits.h | 6 +-- Eigen/src/Core/ProductEvaluators.h | 12 ++++-- Eigen/src/Core/Redux.h | 8 ++-- Eigen/src/Core/Visitor.h | 4 +- Eigen/src/Core/util/Constants.h | 8 ++++ Eigen/src/Core/util/StaticAssert.h | 7 ++- Eigen/src/Core/util/XprHelper.h | 16 ++----- Eigen/src/SparseCore/SparseCompressedBase.h | 10 ++++- Eigen/src/SparseCore/SparseCwiseBinaryOp.h | 20 +++++++-- Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 14 ++++-- Eigen/src/SparseCore/SparseDenseProduct.h | 12 ++++-- Eigen/src/SparseCore/SparseDiagonalProduct.h | 6 +-- Eigen/src/SparseCore/SparseProduct.h | 2 +- Eigen/src/SparseCore/SparseTriangularView.h | 2 +- Eigen/src/SparseCore/SparseVector.h | 8 ++-- test/redux.cpp | 1 - test/vectorwiseop.cpp | 5 +++ .../src/KroneckerProduct/KroneckerTensorProduct.h | 2 +- unsupported/Eigen/src/Skyline/SkylineProduct.h | 2 +- 22 files changed, 139 insertions(+), 68 deletions(-) (limited to 'Eigen/src/Core/CoreEvaluators.h') diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index ba7748395..e66cf074f 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -98,10 +98,10 @@ private: enum { UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1), MayUnrollCompletely = int(Dst::SizeAtCompileTime) != Dynamic - && int(SrcEvaluator::CoeffReadCost) != Dynamic + && int(SrcEvaluator::CoeffReadCost) < HugeCost && int(Dst::SizeAtCompileTime) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit), MayUnrollInner = int(InnerSize) != Dynamic - && int(SrcEvaluator::CoeffReadCost) != Dynamic + && int(SrcEvaluator::CoeffReadCost) < HugeCost && int(InnerSize) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit) }; diff --git a/Eigen/src/Core/BooleanRedux.h b/Eigen/src/Core/BooleanRedux.h index be4cd9b3a..bda9f6966 100644 --- a/Eigen/src/Core/BooleanRedux.h +++ b/Eigen/src/Core/BooleanRedux.h @@ -83,8 +83,8 @@ inline bool DenseBase::all() const typedef internal::evaluator Evaluator; enum { unroll = SizeAtCompileTime != Dynamic - && Evaluator::CoeffReadCost != Dynamic - && NumTraits::AddCost != Dynamic + && Evaluator::CoeffReadCost < HugeCost + && NumTraits::AddCost < HugeCost && SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT }; Evaluator evaluator(derived()); @@ -109,8 +109,8 @@ inline bool DenseBase::any() const typedef internal::evaluator Evaluator; enum { unroll = SizeAtCompileTime != Dynamic - && Evaluator::CoeffReadCost != Dynamic - && NumTraits::AddCost != Dynamic + && Evaluator::CoeffReadCost < HugeCost + && NumTraits::AddCost < HugeCost && SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits::AddCost) <= EIGEN_UNROLLING_LIMIT }; Evaluator evaluator(derived()); diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index c898b2abc..fb0cdc99c 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -137,11 +137,15 @@ struct evaluator > m_outerStride(IsVectorAtCompileTime ? 0 : int(IsRowMajor) ? ColsAtCompileTime : RowsAtCompileTime) - {} + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } EIGEN_DEVICE_FUNC explicit evaluator(const PlainObjectType& m) : m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index row, Index col) const { @@ -327,7 +331,9 @@ struct evaluator > EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n) : m_functor(n.functor()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -376,7 +382,10 @@ struct unary_evaluator, IndexBased > EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -449,7 +458,10 @@ struct binary_evaluator, IndexBased, IndexBase : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -502,7 +514,10 @@ struct unary_evaluator, IndexBased> EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op) : m_unaryOp(op.functor()), m_argImpl(op.nestedExpression()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -559,6 +574,7 @@ struct mapbase_evaluator : evaluator_base { EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator::Flags&PacketAccessBit, internal::inner_stride_at_compile_time::ret==1), PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index row, Index col) const @@ -713,7 +729,10 @@ struct evaluator > Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator::Alignment, Alignment0) }; typedef block_evaluator block_evaluator_type; - EIGEN_DEVICE_FUNC explicit evaluator(const XprType& block) : block_evaluator_type(block) {} + EIGEN_DEVICE_FUNC explicit evaluator(const XprType& block) : block_evaluator_type(block) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } }; // no direct-access => dispatch to a unary evaluator @@ -831,8 +850,8 @@ struct evaluator > typedef Select XprType; enum { CoeffReadCost = evaluator::CoeffReadCost - + EIGEN_SIZE_MAX(evaluator::CoeffReadCost, - evaluator::CoeffReadCost), + + EIGEN_PLAIN_ENUM_MAX(evaluator::CoeffReadCost, + evaluator::CoeffReadCost), Flags = (unsigned int)evaluator::Flags & evaluator::Flags & HereditaryBits, @@ -843,7 +862,9 @@ struct evaluator > : m_conditionImpl(select.conditionMatrix()), m_thenImpl(select.thenMatrix()), m_elseImpl(select.elseMatrix()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::CoeffReturnType CoeffReturnType; @@ -965,11 +986,11 @@ struct evaluator > typedef typename ArgType::Scalar InputScalar; typedef typename XprType::Scalar Scalar; enum { - TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(XprType::ColsAtCompileTime) + TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(ArgType::ColsAtCompileTime) }; typedef typename MemberOp::template Cost CostOpType; enum { - CoeffReadCost = TraversalSize==Dynamic ? Dynamic + CoeffReadCost = TraversalSize==Dynamic ? HugeCost : TraversalSize * evaluator::CoeffReadCost + int(CostOpType::value), Flags = (traits::Flags&RowMajorBit) | (evaluator::Flags&HereditaryBits), @@ -979,7 +1000,10 @@ struct evaluator > EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr) : m_arg(xpr.nestedExpression()), m_functor(xpr.functor()) - {} + { + EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize==Dynamic ? HugeCost : int(CostOpType::value)); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } typedef typename XprType::CoeffReturnType CoeffReturnType; diff --git a/Eigen/src/Core/NumTraits.h b/Eigen/src/Core/NumTraits.h index 61ec2f533..1d85dec72 100644 --- a/Eigen/src/Core/NumTraits.h +++ b/Eigen/src/Core/NumTraits.h @@ -157,9 +157,9 @@ struct NumTraits > IsInteger = NumTraits::IsInteger, IsSigned = NumTraits::IsSigned, RequireInitialization = 1, - ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits::ReadCost, - AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits::AddCost, - MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits::MulCost + ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits::ReadCost, + AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits::AddCost, + MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits::MulCost }; static inline RealScalar epsilon() { return NumTraits::epsilon(); } diff --git a/Eigen/src/Core/ProductEvaluators.h b/Eigen/src/Core/ProductEvaluators.h index 04dc08957..e7677b90c 100755 --- a/Eigen/src/Core/ProductEvaluators.h +++ b/Eigen/src/Core/ProductEvaluators.h @@ -422,7 +422,11 @@ struct product_evaluator, ProductTag, DenseShape, m_rhsImpl(m_rhs), // Moreover, they are only useful for the packet path, so we could completely disable them when not needed, // or perhaps declare them on the fly on the packet method... We have experiment to check what's best. m_innerDim(xpr.lhs().cols()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::MulCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::AddCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } // Everything below here is taken from CoeffBasedProduct.h @@ -447,11 +451,11 @@ struct product_evaluator, ProductTag, DenseShape, LhsCoeffReadCost = LhsEtorType::CoeffReadCost, RhsCoeffReadCost = RhsEtorType::CoeffReadCost, CoeffReadCost = InnerSize==0 ? NumTraits::ReadCost - : (InnerSize == Dynamic || LhsCoeffReadCost==Dynamic || RhsCoeffReadCost==Dynamic || NumTraits::AddCost==Dynamic || NumTraits::MulCost==Dynamic) ? Dynamic + : InnerSize == Dynamic ? HugeCost : InnerSize * (NumTraits::MulCost + LhsCoeffReadCost + RhsCoeffReadCost) + (InnerSize - 1) * NumTraits::AddCost, - Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT, + Unroll = CoeffReadCost < HugeCost && CoeffReadCost <= EIGEN_UNROLLING_LIMIT, LhsFlags = LhsEtorType::Flags, RhsFlags = RhsEtorType::Flags, @@ -736,6 +740,8 @@ public: diagonal_product_evaluator_base(const MatrixType &mat, const DiagonalType &diag) : m_diagImpl(diag), m_matImpl(mat) { + EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits::MulCost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h index 309898b36..fcf0ba76a 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -51,9 +51,9 @@ public: public: enum { Cost = ( Derived::SizeAtCompileTime == Dynamic - || Derived::CoeffReadCost == Dynamic - || (Derived::SizeAtCompileTime!=1 && functor_traits::Cost == Dynamic) - ) ? Dynamic + || Derived::CoeffReadCost >= HugeCost + || (Derived::SizeAtCompileTime!=1 && functor_traits::Cost >= HugeCost) + ) ? HugeCost : Derived::SizeAtCompileTime * Derived::CoeffReadCost + (Derived::SizeAtCompileTime-1) * functor_traits::Cost, UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize)) @@ -61,7 +61,7 @@ public: public: enum { - Unrolling = Cost != Dynamic && Cost <= UnrollingLimit + Unrolling = Cost < HugeCost && Cost <= UnrollingLimit ? CompleteUnrolling : NoUnrolling }; diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h index a4e2cebab..f3f15e9e0 100644 --- a/Eigen/src/Core/Visitor.h +++ b/Eigen/src/Core/Visitor.h @@ -110,8 +110,8 @@ void DenseBase::visit(Visitor& visitor) const ThisEvaluator thisEval(derived()); enum { unroll = SizeAtCompileTime != Dynamic - && ThisEvaluator::CoeffReadCost != Dynamic - && (SizeAtCompileTime == 1 || internal::functor_traits::Cost != Dynamic) + && ThisEvaluator::CoeffReadCost < HugeCost + && (SizeAtCompileTime == 1 || internal::functor_traits::Cost < HugeCost) && SizeAtCompileTime * ThisEvaluator::CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits::Cost <= EIGEN_UNROLLING_LIMIT }; return internal::visitor_impl::value), \ YOU_CANNOT_MIX_ARRAYS_AND_MATRICES) +// Check that a cost value is positive, and that is stay within a reasonable range +// TODO this check could be enabled for internal debugging only +#define EIGEN_INTERNAL_CHECK_COST_VALUE(C) \ + EIGEN_STATIC_ASSERT((C)>=0 && (C)<2*HugeCost*HugeCost, EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE); #endif // EIGEN_STATIC_ASSERT_H diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index cd93b2320..209c73e1e 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -397,28 +397,20 @@ struct transfer_constness template::type> struct nested_eval { enum { - // For the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values. - // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values. - // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues - // (poor choice of temporaries). - // It's important that this value can still be squared without integer overflowing. - DynamicAsInteger = 10000, ScalarReadCost = NumTraits::Scalar>::ReadCost, - ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost), CoeffReadCost = evaluator::CoeffReadCost, // NOTE What if an evaluator evaluate itself into a tempory? // Then CoeffReadCost will be small (e.g., 1) but we still have to evaluate, especially if n>1. // This situation is already taken care by the EvalBeforeNestingBit flag, which is turned ON // for all evaluator creating a temporary. This flag is then propagated by the parent evaluators. // Another solution could be to count the number of temps? - CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost), - NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n, - CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger, - CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger + NAsInteger = n == Dynamic ? HugeCost : n, + CostEval = (NAsInteger+1) * ScalarReadCost + CoeffReadCost, + CostNoEval = NAsInteger * CoeffReadCost }; typedef typename conditional< ( (int(evaluator::Flags) & EvalBeforeNestingBit) || - (int(CostEvalAsInteger) < int(CostNoEvalAsInteger)) ), + (int(CostEval) < int(CostNoEval)) ), PlainObject, typename ref_selector::type >::type type; diff --git a/Eigen/src/SparseCore/SparseCompressedBase.h b/Eigen/src/SparseCore/SparseCompressedBase.h index c8a2705f9..fb795a0ed 100644 --- a/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/Eigen/src/SparseCore/SparseCompressedBase.h @@ -226,8 +226,14 @@ struct evaluator > Flags = Derived::Flags }; - evaluator() : m_matrix(0) {} - explicit evaluator(const Derived &mat) : m_matrix(&mat) {} + evaluator() : m_matrix(0) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } + explicit evaluator(const Derived &mat) : m_matrix(&mat) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_matrix->nonZeros(); diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index b87b6b749..abbbf397b 100644 --- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -139,7 +139,10 @@ public: : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); @@ -220,7 +223,10 @@ public: : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate()); @@ -289,7 +295,10 @@ public: : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_rhsImpl.nonZerosEstimate(); @@ -359,7 +368,10 @@ public: : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) - { } + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate(); diff --git a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h index 469bac36e..fe4a97120 100644 --- a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2008-2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -29,7 +29,11 @@ struct unary_evaluator, IteratorBased> Flags = XprType::Flags }; - explicit unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) {} + explicit unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_argImpl.nonZerosEstimate(); @@ -108,7 +112,11 @@ struct unary_evaluator, IteratorBased> Flags = XprType::Flags }; - explicit unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) {} + explicit unary_evaluator(const XprType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits::Cost); + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } protected: typedef typename evaluator::InnerIterator EvalIterator; diff --git a/Eigen/src/SparseCore/SparseDenseProduct.h b/Eigen/src/SparseCore/SparseDenseProduct.h index 2e34ae74c..87c946b9b 100644 --- a/Eigen/src/SparseCore/SparseDenseProduct.h +++ b/Eigen/src/SparseCore/SparseDenseProduct.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2008-2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -221,7 +221,7 @@ protected: public: enum { Flags = NeedToTranspose ? RowMajorBit : 0, - CoeffReadCost = Dynamic + CoeffReadCost = HugeCost }; class InnerIterator : public LhsIterator @@ -263,12 +263,16 @@ public: sparse_dense_outer_product_evaluator(const Lhs1 &lhs, const ActualRhs &rhs) : m_lhs(lhs), m_lhsXprImpl(m_lhs), m_rhsXprImpl(rhs) - {} + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } // transpose case sparse_dense_outer_product_evaluator(const ActualRhs &rhs, const Lhs1 &lhs) : m_lhs(lhs), m_lhsXprImpl(m_lhs), m_rhsXprImpl(rhs) - {} + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } protected: const LhsArg m_lhs; diff --git a/Eigen/src/SparseCore/SparseDiagonalProduct.h b/Eigen/src/SparseCore/SparseDiagonalProduct.h index cf31e5a53..e4af49e09 100644 --- a/Eigen/src/SparseCore/SparseDiagonalProduct.h +++ b/Eigen/src/SparseCore/SparseDiagonalProduct.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2009-2014 Gael Guennebaud +// Copyright (C) 2009-2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -39,7 +39,7 @@ struct product_evaluator, ProductTag, Diagonal : public sparse_diagonal_product_evaluator { typedef Product XprType; - enum { CoeffReadCost = Dynamic, Flags = Rhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags + enum { CoeffReadCost = HugeCost, Flags = Rhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags typedef sparse_diagonal_product_evaluator Base; explicit product_evaluator(const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {} @@ -50,7 +50,7 @@ struct product_evaluator, ProductTag, SparseSh : public sparse_diagonal_product_evaluator, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct> { typedef Product XprType; - enum { CoeffReadCost = Dynamic, Flags = Lhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags + enum { CoeffReadCost = HugeCost, Flags = Lhs::Flags&RowMajorBit, Alignment = 0 }; // FIXME CoeffReadCost & Flags typedef sparse_diagonal_product_evaluator, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct> Base; explicit product_evaluator(const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal().transpose()) {} diff --git a/Eigen/src/SparseCore/SparseProduct.h b/Eigen/src/SparseCore/SparseProduct.h index ea2c3a8a3..cbd0db71b 100644 --- a/Eigen/src/SparseCore/SparseProduct.h +++ b/Eigen/src/SparseCore/SparseProduct.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2008-2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed diff --git a/Eigen/src/SparseCore/SparseTriangularView.h b/Eigen/src/SparseCore/SparseTriangularView.h index 57d88893e..7c718e4e1 100644 --- a/Eigen/src/SparseCore/SparseTriangularView.h +++ b/Eigen/src/SparseCore/SparseTriangularView.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2009-2014 Gael Guennebaud +// Copyright (C) 2009-2015 Gael Guennebaud // Copyright (C) 2012 Désiré Nuentsa-Wakam // // This Source Code Form is subject to the terms of the Mozilla diff --git a/Eigen/src/SparseCore/SparseVector.h b/Eigen/src/SparseCore/SparseVector.h index 94f8d0341..7ec73a365 100644 --- a/Eigen/src/SparseCore/SparseVector.h +++ b/Eigen/src/SparseCore/SparseVector.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2014 Gael Guennebaud +// Copyright (C) 2008-2015 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -41,7 +41,6 @@ struct traits > MaxRowsAtCompileTime = RowsAtCompileTime, MaxColsAtCompileTime = ColsAtCompileTime, Flags = _Options | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit) | CompressedAccessBit, - CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = InnerRandomAccessPattern }; }; @@ -380,7 +379,10 @@ struct evaluator > Flags = SparseVectorType::Flags }; - explicit evaluator(const SparseVectorType &mat) : m_matrix(mat) {} + explicit evaluator(const SparseVectorType &mat) : m_matrix(mat) + { + EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); + } inline Index nonZerosEstimate() const { return m_matrix.nonZeros(); diff --git a/test/redux.cpp b/test/redux.cpp index bfd9a8d50..6ddc59c18 100644 --- a/test/redux.cpp +++ b/test/redux.cpp @@ -74,7 +74,6 @@ template void matrixRedux(const MatrixType& m) Matrix m2(rows,rows); m2.setRandom(); VERIFY_EVALUATION_COUNT( ((m1.matrix()*m1.matrix().transpose())+m2).sum(), (MatrixType::SizeAtCompileTime==Dynamic ? 1 : 0) ); - } template void vectorRedux(const VectorType& w) diff --git a/test/vectorwiseop.cpp b/test/vectorwiseop.cpp index ddd9f8389..529f4298b 100644 --- a/test/vectorwiseop.cpp +++ b/test/vectorwiseop.cpp @@ -217,6 +217,11 @@ template void vectorwiseop_matrix(const MatrixType& m) VERIFY_IS_APPROX( (m1 * m1.transpose()).colwise().sum(), m1m1.colwise().sum()); Matrix tmp(rows); VERIFY_EVALUATION_COUNT( tmp = (m1 * m1.transpose()).colwise().sum(), (MatrixType::RowsAtCompileTime==Dynamic ? 1 : 0)); + + m2 = m1.rowwise() - (m1.colwise().sum()/m1.rows()).eval(); + m1 = m1.rowwise() - (m1.colwise().sum()/m1.rows()); + VERIFY_IS_APPROX( m1, m2 ); + VERIFY_EVALUATION_COUNT( m2 = (m1.rowwise() - m1.colwise().sum()/m1.rows()), (MatrixType::RowsAtCompileTime==Dynamic ? 1 : 0) ); } void test_vectorwiseop() diff --git a/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h b/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h index 4406437cc..4d3e5358e 100644 --- a/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h +++ b/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h @@ -240,7 +240,7 @@ struct traits > Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits) | EvalBeforeNestingBit | EvalBeforeAssigningBit, - CoeffReadCost = Dynamic + CoeffReadCost = HugeCost }; typedef SparseMatrix ReturnType; diff --git a/unsupported/Eigen/src/Skyline/SkylineProduct.h b/unsupported/Eigen/src/Skyline/SkylineProduct.h index d218a7c25..d9eb814c1 100644 --- a/unsupported/Eigen/src/Skyline/SkylineProduct.h +++ b/unsupported/Eigen/src/Skyline/SkylineProduct.h @@ -49,7 +49,7 @@ struct internal::traits > { | EvalBeforeAssigningBit | EvalBeforeNestingBit, - CoeffReadCost = Dynamic + CoeffReadCost = HugeCost }; typedef typename internal::conditional