mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-02-23 18:20:47 +08:00
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)
This commit is contained in:
parent
827d8a9bad
commit
77ff3386b7
@ -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)
|
||||
};
|
||||
|
||||
|
@ -83,8 +83,8 @@ inline bool DenseBase<Derived>::all() const
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& Evaluator::CoeffReadCost != Dynamic
|
||||
&& NumTraits<Scalar>::AddCost != Dynamic
|
||||
&& Evaluator::CoeffReadCost < HugeCost
|
||||
&& NumTraits<Scalar>::AddCost < HugeCost
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
@ -109,8 +109,8 @@ inline bool DenseBase<Derived>::any() const
|
||||
typedef internal::evaluator<Derived> Evaluator;
|
||||
enum {
|
||||
unroll = SizeAtCompileTime != Dynamic
|
||||
&& Evaluator::CoeffReadCost != Dynamic
|
||||
&& NumTraits<Scalar>::AddCost != Dynamic
|
||||
&& Evaluator::CoeffReadCost < HugeCost
|
||||
&& NumTraits<Scalar>::AddCost < HugeCost
|
||||
&& SizeAtCompileTime * (Evaluator::CoeffReadCost + NumTraits<Scalar>::AddCost) <= EIGEN_UNROLLING_LIMIT
|
||||
};
|
||||
Evaluator evaluator(derived());
|
||||
|
@ -137,11 +137,15 @@ struct evaluator<PlainObjectBase<Derived> >
|
||||
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<CwiseNullaryOp<NullaryOp,PlainObjectType> >
|
||||
|
||||
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<CwiseUnaryOp<UnaryOp, ArgType>, 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<UnaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
@ -449,7 +458,10 @@ struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBase
|
||||
: m_functor(xpr.functor()),
|
||||
m_lhsImpl(xpr.lhs()),
|
||||
m_rhsImpl(xpr.rhs())
|
||||
{ }
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
@ -502,7 +514,10 @@ struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, 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<UnaryOp>::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<Derived>
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator<Derived>::Flags&PacketAccessBit, internal::inner_stride_at_compile_time<Derived>::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<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
|
||||
Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ArgType>::Alignment, Alignment0)
|
||||
};
|
||||
typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> 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<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
|
||||
typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost
|
||||
+ EIGEN_SIZE_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
|
||||
evaluator<ElseMatrixType>::CoeffReadCost),
|
||||
+ EIGEN_PLAIN_ENUM_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
|
||||
evaluator<ElseMatrixType>::CoeffReadCost),
|
||||
|
||||
Flags = (unsigned int)evaluator<ThenMatrixType>::Flags & evaluator<ElseMatrixType>::Flags & HereditaryBits,
|
||||
|
||||
@ -843,7 +862,9 @@ struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
|
||||
: 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<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
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<InputScalar,int(TraversalSize)> CostOpType;
|
||||
enum {
|
||||
CoeffReadCost = TraversalSize==Dynamic ? Dynamic
|
||||
CoeffReadCost = TraversalSize==Dynamic ? HugeCost
|
||||
: TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value),
|
||||
|
||||
Flags = (traits<XprType>::Flags&RowMajorBit) | (evaluator<ArgType>::Flags&HereditaryBits),
|
||||
@ -979,7 +1000,10 @@ struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
|
||||
|
||||
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;
|
||||
|
||||
|
@ -157,9 +157,9 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
||||
IsInteger = NumTraits<Scalar>::IsInteger,
|
||||
IsSigned = NumTraits<Scalar>::IsSigned,
|
||||
RequireInitialization = 1,
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::ReadCost,
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? Dynamic : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
||||
ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::ReadCost,
|
||||
AddCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::AddCost,
|
||||
MulCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * NumTraits<Scalar>::MulCost
|
||||
};
|
||||
|
||||
static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||
|
@ -422,7 +422,11 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, 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<Scalar>::MulCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(NumTraits<Scalar>::AddCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
// Everything below here is taken from CoeffBasedProduct.h
|
||||
|
||||
@ -447,11 +451,11 @@ struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape,
|
||||
LhsCoeffReadCost = LhsEtorType::CoeffReadCost,
|
||||
RhsCoeffReadCost = RhsEtorType::CoeffReadCost,
|
||||
CoeffReadCost = InnerSize==0 ? NumTraits<Scalar>::ReadCost
|
||||
: (InnerSize == Dynamic || LhsCoeffReadCost==Dynamic || RhsCoeffReadCost==Dynamic || NumTraits<Scalar>::AddCost==Dynamic || NumTraits<Scalar>::MulCost==Dynamic) ? Dynamic
|
||||
: InnerSize == Dynamic ? HugeCost
|
||||
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
||||
+ (InnerSize - 1) * NumTraits<Scalar>::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<Scalar>::MulCost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar coeff(Index idx) const
|
||||
|
@ -51,9 +51,9 @@ public:
|
||||
public:
|
||||
enum {
|
||||
Cost = ( Derived::SizeAtCompileTime == Dynamic
|
||||
|| Derived::CoeffReadCost == Dynamic
|
||||
|| (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost == Dynamic)
|
||||
) ? Dynamic
|
||||
|| Derived::CoeffReadCost >= HugeCost
|
||||
|| (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost >= HugeCost)
|
||||
) ? HugeCost
|
||||
: Derived::SizeAtCompileTime * Derived::CoeffReadCost
|
||||
+ (Derived::SizeAtCompileTime-1) * functor_traits<Func>::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
|
||||
};
|
||||
|
@ -110,8 +110,8 @@ void DenseBase<Derived>::visit(Visitor& visitor) const
|
||||
ThisEvaluator thisEval(derived());
|
||||
|
||||
enum { unroll = SizeAtCompileTime != Dynamic
|
||||
&& ThisEvaluator::CoeffReadCost != Dynamic
|
||||
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
|
||||
&& ThisEvaluator::CoeffReadCost < HugeCost
|
||||
&& (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost < HugeCost)
|
||||
&& SizeAtCompileTime * ThisEvaluator::CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
|
||||
<= EIGEN_UNROLLING_LIMIT };
|
||||
return internal::visitor_impl<Visitor, ThisEvaluator,
|
||||
|
@ -30,6 +30,14 @@ const int DynamicIndex = 0xffffff;
|
||||
*/
|
||||
const int Infinity = -1;
|
||||
|
||||
/** This value means that the cost to evaluate an expression coefficient is either very expensive or
|
||||
* cannot be known at compile time.
|
||||
*
|
||||
* This value has to be positive to (1) simplify cost computation, and (2) allow to distinguish between a very expensive and very very expensive expressions.
|
||||
* It thus must also be large enough to make sure unrolling won't happen and that sub expressions will be evaluated, but not too large to avoid overflow.
|
||||
*/
|
||||
const int HugeCost = 1000;
|
||||
|
||||
/** \defgroup flags Flags
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
|
@ -93,7 +93,8 @@
|
||||
THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH,
|
||||
OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG,
|
||||
IMPLICIT_CONVERSION_TO_SCALAR_IS_FOR_INNER_PRODUCT_ONLY,
|
||||
STORAGE_LAYOUT_DOES_NOT_MATCH
|
||||
STORAGE_LAYOUT_DOES_NOT_MATCH,
|
||||
EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT__INVALID_COST_VALUE
|
||||
};
|
||||
};
|
||||
|
||||
@ -200,5 +201,9 @@
|
||||
>::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
|
||||
|
@ -397,28 +397,20 @@ struct transfer_constness
|
||||
template<typename T, int n, typename PlainObject = typename plain_object_eval<T>::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<typename traits<T>::Scalar>::ReadCost,
|
||||
ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost),
|
||||
CoeffReadCost = evaluator<T>::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<T>::Flags) & EvalBeforeNestingBit) ||
|
||||
(int(CostEvalAsInteger) < int(CostNoEvalAsInteger)) ),
|
||||
(int(CostEval) < int(CostNoEval)) ),
|
||||
PlainObject,
|
||||
typename ref_selector<T>::type
|
||||
>::type type;
|
||||
|
@ -226,8 +226,14 @@ struct evaluator<SparseCompressedBase<Derived> >
|
||||
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();
|
||||
|
@ -139,7 +139,10 @@ public:
|
||||
: m_functor(xpr.functor()),
|
||||
m_lhsImpl(xpr.lhs()),
|
||||
m_rhsImpl(xpr.rhs())
|
||||
{ }
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::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<BinaryOp>::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<BinaryOp>::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<BinaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
inline Index nonZerosEstimate() const {
|
||||
return m_lhsImpl.nonZerosEstimate();
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// 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<CwiseUnaryOp<UnaryOp,ArgType>, 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<UnaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
inline Index nonZerosEstimate() const {
|
||||
return m_argImpl.nonZerosEstimate();
|
||||
@ -108,7 +112,11 @@ struct unary_evaluator<CwiseUnaryView<ViewOp,ArgType>, 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<ViewOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef typename evaluator<ArgType>::InnerIterator EvalIterator;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// 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;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2009-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// 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<Product<Lhs, Rhs, DefaultProduct>, ProductTag, Diagonal
|
||||
: public sparse_diagonal_product_evaluator<Rhs, typename Lhs::DiagonalVectorType, Rhs::Flags&RowMajorBit?SDP_AsScalarProduct:SDP_AsCwiseProduct>
|
||||
{
|
||||
typedef Product<Lhs, Rhs, DefaultProduct> 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<Rhs, typename Lhs::DiagonalVectorType, Rhs::Flags&RowMajorBit?SDP_AsScalarProduct:SDP_AsCwiseProduct> Base;
|
||||
explicit product_evaluator(const XprType& xpr) : Base(xpr.rhs(), xpr.lhs().diagonal()) {}
|
||||
@ -50,7 +50,7 @@ struct product_evaluator<Product<Lhs, Rhs, DefaultProduct>, ProductTag, SparseSh
|
||||
: public sparse_diagonal_product_evaluator<Lhs, Transpose<const typename Rhs::DiagonalVectorType>, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct>
|
||||
{
|
||||
typedef Product<Lhs, Rhs, DefaultProduct> 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, Transpose<const typename Rhs::DiagonalVectorType>, Lhs::Flags&RowMajorBit?SDP_AsCwiseProduct:SDP_AsScalarProduct> Base;
|
||||
explicit product_evaluator(const XprType& xpr) : Base(xpr.lhs(), xpr.rhs().diagonal().transpose()) {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2009-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// 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<SparseVector<_Scalar, _Options, _StorageIndex> >
|
||||
MaxRowsAtCompileTime = RowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ColsAtCompileTime,
|
||||
Flags = _Options | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit) | CompressedAccessBit,
|
||||
CoeffReadCost = NumTraits<Scalar>::ReadCost,
|
||||
SupportedAccessPatterns = InnerRandomAccessPattern
|
||||
};
|
||||
};
|
||||
@ -380,7 +379,10 @@ struct evaluator<SparseVector<_Scalar,_Options,_Index> >
|
||||
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();
|
||||
|
@ -74,7 +74,6 @@ template<typename MatrixType> void matrixRedux(const MatrixType& m)
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> m2(rows,rows);
|
||||
m2.setRandom();
|
||||
VERIFY_EVALUATION_COUNT( ((m1.matrix()*m1.matrix().transpose())+m2).sum(), (MatrixType::SizeAtCompileTime==Dynamic ? 1 : 0) );
|
||||
|
||||
}
|
||||
|
||||
template<typename VectorType> void vectorRedux(const VectorType& w)
|
||||
|
@ -217,6 +217,11 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
|
||||
VERIFY_IS_APPROX( (m1 * m1.transpose()).colwise().sum(), m1m1.colwise().sum());
|
||||
Matrix<Scalar,1,MatrixType::RowsAtCompileTime> 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()
|
||||
|
@ -240,7 +240,7 @@ struct traits<KroneckerProductSparse<_Lhs,_Rhs> >
|
||||
|
||||
Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits)
|
||||
| EvalBeforeNestingBit | EvalBeforeAssigningBit,
|
||||
CoeffReadCost = Dynamic
|
||||
CoeffReadCost = HugeCost
|
||||
};
|
||||
|
||||
typedef SparseMatrix<Scalar, 0, StorageIndex> ReturnType;
|
||||
|
@ -49,7 +49,7 @@ struct internal::traits<SkylineProduct<LhsNested, RhsNested, ProductMode> > {
|
||||
| EvalBeforeAssigningBit
|
||||
| EvalBeforeNestingBit,
|
||||
|
||||
CoeffReadCost = Dynamic
|
||||
CoeffReadCost = HugeCost
|
||||
};
|
||||
|
||||
typedef typename internal::conditional<ResultIsSkyline,
|
||||
|
Loading…
Reference in New Issue
Block a user