1- Introduce sub-evaluator types for unary, binary, product, and map expressions to ease specializing them.

2- Remove a lot of code which should not be there with evaluators, in particular coeff/packet methods implemented in the expressions.
This commit is contained in:
Gael Guennebaud 2014-06-20 15:39:38 +02:00
parent 0a6c472335
commit 78bb808337
18 changed files with 300 additions and 159 deletions

View File

@ -123,7 +123,11 @@ template<typename Derived> class ArrayBase
EIGEN_DEVICE_FUNC
Derived& operator=(const ArrayBase& other)
{
#ifndef EIGEN_TEST_EVALUATORS
return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
#else
internal::call_assignment(derived(), other.derived());
#endif
}
EIGEN_DEVICE_FUNC

View File

@ -39,6 +39,7 @@ class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> >
typedef ArrayBase<ArrayWrapper> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper)
typedef typename internal::remove_all<ExpressionType>::type NestedExpression;
typedef typename internal::conditional<
internal::is_lvalue<ExpressionType>::value,
@ -176,6 +177,7 @@ class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> >
typedef MatrixBase<MatrixWrapper<ExpressionType> > Base;
EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper)
typedef typename internal::remove_all<ExpressionType>::type NestedExpression;
typedef typename internal::conditional<
internal::is_lvalue<ExpressionType>::value,

View File

@ -344,6 +344,9 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
: public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >
{
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
enum {
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0
};
public:
typedef MapBase<BlockType> Base;
@ -354,9 +357,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
*/
EIGEN_DEVICE_FUNC
inline BlockImpl_dense(XprType& xpr, Index i)
: Base(internal::const_cast_ptr(&xpr.coeffRef(
(BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
(BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
: Base(xpr.data() + i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor))
|| ((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && ( XprTypeIsRowMajor)) ? xpr.innerStride() : xpr.outerStride()),
BlockRows==1 ? 1 : xpr.rows(),
BlockCols==1 ? 1 : xpr.cols()),
m_xpr(xpr)
@ -368,7 +370,8 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
*/
EIGEN_DEVICE_FUNC
inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol)),
m_xpr(xpr)
{
init();
}
@ -379,7 +382,7 @@ class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
inline BlockImpl_dense(XprType& xpr,
Index startRow, Index startCol,
Index blockRows, Index blockCols)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
: Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol), blockRows, blockCols),
m_xpr(xpr)
{
init();

View File

@ -27,14 +27,6 @@ struct storage_kind_to_evaluator_kind {
typedef IndexBased Kind;
};
// TODO to be moved to SparseCore:
/*
template<>
struct storage_kind_to_evaluator_kind<Sparse> {
typedef IteratorBased Kind
};
*/
// This class returns the evaluator shape from the expression storage kind.
// It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc.
template<typename StorageKind> struct storage_kind_to_shape;
@ -45,22 +37,28 @@ struct storage_kind_to_shape<Dense> {
typedef DenseShape Shape;
};
// TODO to be moved to SparseCore:
/*
template<>
struct storage_kind_to_shape<Sparse> {
typedef SparseSpape Shape;
};
*/
// Evaluators have to be specialized with respect to various criteria such as:
// - storage/structure/shape
// - scalar type
// - etc.
// Therefore, we need specialization of evaluator providing additional template arguments for each kind of evaluators.
// We currently distinguish the following kind of evaluators:
// - unary_evaluator for expressions taking only one arguments (CwiseUnaryOp, CwiseUnaryView, Transpose, MatrixWrapper, ArrayWrapper, Reverse, Replicate)
// - binary_evaluator for expression taking two arguments (CwiseBinaryOp)
// - product_evaluator for linear algebra products (Product); special case of binary_evaluator because it requires additional tags for dispatching.
// - mapbase_evaluator for Map, Block, Ref
// - block_evaluator for Block (special dispatching to a mapbase_evaluator or unary_evaluator)
template< typename T,
typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
typename LhsScalar = typename T::Lhs::Scalar,
typename RhsScalar = typename T::Rhs::Scalar> struct binary_evaluator;
template< typename T,
typename Kind = typename evaluator_traits<typename T::NestedExpression>::Kind,
typename Scalar = typename T::Scalar> struct unary_evaluator;
// evaluator_traits<T> contains traits for evaluator<T>
template<typename T>
@ -80,15 +78,20 @@ struct evaluator_traits_base
static const int AssumeAliasing = 0;
};
// Default evaluator traits
template<typename T>
struct evaluator_traits : public evaluator_traits_base<T>
{
};
// expression class for evaluating nested expression to a temporary
template<typename ArgType>
class EvalToTemp;
// By default, we assume a unary expression:
template<typename T>
struct evaluator : public unary_evaluator<T>
{
typedef unary_evaluator<T> Base;
evaluator(const T& xpr) : Base(xpr) {}
};
// TODO: Think about const-correctness
@ -118,6 +121,8 @@ struct evaluator_base
//
// evaluator<PlainObjectBase> is a common base class for the
// Matrix and Array evaluators.
// Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense,
// so no need for more sophisticated dispatching.
template<typename Derived>
struct evaluator<PlainObjectBase<Derived> >
@ -245,81 +250,10 @@ struct evaluator<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
{ }
};
// -------------------- EvalToTemp --------------------
template<typename ArgType>
struct traits<EvalToTemp<ArgType> >
: public traits<ArgType>
{ };
template<typename ArgType>
class EvalToTemp
: public dense_xpr_base<EvalToTemp<ArgType> >::type
{
public:
typedef typename dense_xpr_base<EvalToTemp>::type Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
EvalToTemp(const ArgType& arg)
: m_arg(arg)
{ }
const ArgType& arg() const
{
return m_arg;
}
Index rows() const
{
return m_arg.rows();
}
Index cols() const
{
return m_arg.cols();
}
private:
const ArgType& m_arg;
};
template<typename ArgType>
struct evaluator<EvalToTemp<ArgType> >
: public evaluator<typename ArgType::PlainObject>::type
{
typedef EvalToTemp<ArgType> XprType;
typedef typename ArgType::PlainObject PlainObject;
typedef typename evaluator<PlainObject>::type Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
// TODO we should simply do m_result(xpr.arg());
call_dense_assignment_loop(m_result, xpr.arg());
}
// This constructor is used when nesting an EvalTo evaluator in another evaluator
evaluator(const ArgType& arg)
: m_result(arg.rows(), arg.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
// TODO we should simply do m_result(xpr.arg());
call_dense_assignment_loop(m_result, arg);
}
protected:
PlainObject m_result;
};
// -------------------- Transpose --------------------
template<typename ArgType>
struct evaluator<Transpose<ArgType> >
struct unary_evaluator<Transpose<ArgType> >
: evaluator_base<Transpose<ArgType> >
{
typedef Transpose<ArgType> XprType;
@ -329,7 +263,7 @@ struct evaluator<Transpose<ArgType> >
Flags = evaluator<ArgType>::Flags ^ RowMajorBit
};
evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
unary_evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
typedef typename XprType::Index Index;
typedef typename XprType::Scalar Scalar;
@ -386,6 +320,8 @@ protected:
};
// -------------------- CwiseNullaryOp --------------------
// Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator.
// Likewise, there is not need to more sophisticated dispatching here.
template<typename NullaryOp, typename PlainObjectType>
struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
@ -441,7 +377,7 @@ protected:
// -------------------- CwiseUnaryOp --------------------
template<typename UnaryOp, typename ArgType>
struct evaluator<CwiseUnaryOp<UnaryOp, ArgType> >
struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
: evaluator_base<CwiseUnaryOp<UnaryOp, ArgType> >
{
typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
@ -454,7 +390,7 @@ struct evaluator<CwiseUnaryOp<UnaryOp, ArgType> >
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0))
};
evaluator(const XprType& op)
unary_evaluator(const XprType& op)
: m_functor(op.functor()),
m_argImpl(op.nestedExpression())
{ }
@ -492,8 +428,19 @@ protected:
// -------------------- CwiseBinaryOp --------------------
// this is a binary expression
template<typename BinaryOp, typename Lhs, typename Rhs>
struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
: public binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
typedef binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > Base;
evaluator(const XprType& xpr) : Base(xpr) {}
};
template<typename BinaryOp, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
: evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
{
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
@ -517,7 +464,7 @@ struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit)
};
evaluator(const XprType& xpr)
binary_evaluator(const XprType& xpr)
: m_functor(xpr.functor()),
m_lhsImpl(xpr.lhs()),
m_rhsImpl(xpr.rhs())
@ -560,7 +507,7 @@ protected:
// -------------------- CwiseUnaryView --------------------
template<typename UnaryOp, typename ArgType>
struct evaluator<CwiseUnaryView<UnaryOp, ArgType> >
struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType> >
: evaluator_base<CwiseUnaryView<UnaryOp, ArgType> >
{
typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
@ -571,7 +518,7 @@ struct evaluator<CwiseUnaryView<UnaryOp, ArgType> >
Flags = (evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit))
};
evaluator(const XprType& op)
unary_evaluator(const XprType& op)
: m_unaryOp(op.functor()),
m_argImpl(op.nestedExpression())
{ }
@ -884,6 +831,7 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAc
// -------------------- Select --------------------
// TODO shall we introduce a ternary_evaluator?
// TODO enable vectorization for Select
template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
@ -934,7 +882,7 @@ protected:
// -------------------- Replicate --------------------
template<typename ArgType, int RowFactor, int ColFactor>
struct evaluator<Replicate<ArgType, RowFactor, ColFactor> >
struct unary_evaluator<Replicate<ArgType, RowFactor, ColFactor> >
: evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
{
typedef Replicate<ArgType, RowFactor, ColFactor> XprType;
@ -953,7 +901,7 @@ struct evaluator<Replicate<ArgType, RowFactor, ColFactor> >
Flags = (evaluator<ArgTypeNestedCleaned>::Flags & HereditaryBits & ~RowMajorBit) | (traits<XprType>::Flags & RowMajorBit)
};
evaluator(const XprType& replicate)
unary_evaluator(const XprType& replicate)
: m_arg(replicate.nestedExpression()),
m_argImpl(m_arg),
m_rows(replicate.nestedExpression().rows()),
@ -1111,23 +1059,23 @@ protected:
};
template<typename TArgType>
struct evaluator<MatrixWrapper<TArgType> >
struct unary_evaluator<MatrixWrapper<TArgType> >
: evaluator_wrapper_base<MatrixWrapper<TArgType> >
{
typedef MatrixWrapper<TArgType> XprType;
evaluator(const XprType& wrapper)
unary_evaluator(const XprType& wrapper)
: evaluator_wrapper_base<MatrixWrapper<TArgType> >(wrapper.nestedExpression())
{ }
};
template<typename TArgType>
struct evaluator<ArrayWrapper<TArgType> >
struct unary_evaluator<ArrayWrapper<TArgType> >
: evaluator_wrapper_base<ArrayWrapper<TArgType> >
{
typedef ArrayWrapper<TArgType> XprType;
evaluator(const XprType& wrapper)
unary_evaluator(const XprType& wrapper)
: evaluator_wrapper_base<ArrayWrapper<TArgType> >(wrapper.nestedExpression())
{ }
};
@ -1139,7 +1087,7 @@ struct evaluator<ArrayWrapper<TArgType> >
template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond;
template<typename ArgType, int Direction>
struct evaluator<Reverse<ArgType, Direction> >
struct unary_evaluator<Reverse<ArgType, Direction> >
: evaluator_base<Reverse<ArgType, Direction> >
{
typedef Reverse<ArgType, Direction> XprType;
@ -1173,7 +1121,7 @@ struct evaluator<Reverse<ArgType, Direction> >
};
typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet;
evaluator(const XprType& reverse)
unary_evaluator(const XprType& reverse)
: m_argImpl(reverse.nestedExpression()),
m_rows(ReverseRow ? reverse.nestedExpression().rows() : 0),
m_cols(ReverseCol ? reverse.nestedExpression().cols() : 0)
@ -1292,6 +1240,87 @@ private:
EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; }
};
//----------------------------------------------------------------------
// deprecated code
//----------------------------------------------------------------------
// -------------------- EvalToTemp --------------------
// expression class for evaluating nested expression to a temporary
template<typename ArgType> class EvalToTemp;
template<typename ArgType>
struct traits<EvalToTemp<ArgType> >
: public traits<ArgType>
{ };
template<typename ArgType>
class EvalToTemp
: public dense_xpr_base<EvalToTemp<ArgType> >::type
{
public:
typedef typename dense_xpr_base<EvalToTemp>::type Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
EvalToTemp(const ArgType& arg)
: m_arg(arg)
{ }
const ArgType& arg() const
{
return m_arg;
}
Index rows() const
{
return m_arg.rows();
}
Index cols() const
{
return m_arg.cols();
}
private:
const ArgType& m_arg;
};
template<typename ArgType>
struct evaluator<EvalToTemp<ArgType> >
: public evaluator<typename ArgType::PlainObject>::type
{
typedef EvalToTemp<ArgType> XprType;
typedef typename ArgType::PlainObject PlainObject;
typedef typename evaluator<PlainObject>::type Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
// TODO we should simply do m_result(xpr.arg());
call_dense_assignment_loop(m_result, xpr.arg());
}
// This constructor is used when nesting an EvalTo evaluator in another evaluator
evaluator(const ArgType& arg)
: m_result(arg.rows(), arg.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
// TODO we should simply do m_result(xpr.arg());
call_dense_assignment_loop(m_result, arg);
}
protected:
PlainObject m_result;
};
} // namespace internal
} // end namespace Eigen

View File

@ -94,23 +94,26 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
class CwiseBinaryOpImpl;
template<typename BinaryOp, typename Lhs, typename Rhs>
template<typename BinaryOp, typename LhsType, typename RhsType>
class CwiseBinaryOp : internal::no_assignment_operator,
public CwiseBinaryOpImpl<
BinaryOp, Lhs, Rhs,
typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
typename internal::traits<Rhs>::StorageKind>::ret>
BinaryOp, LhsType, RhsType,
typename internal::promote_storage_type<typename internal::traits<LhsType>::StorageKind,
typename internal::traits<RhsType>::StorageKind>::ret>
{
public:
typedef typename internal::remove_all<LhsType>::type Lhs;
typedef typename internal::remove_all<RhsType>::type Rhs;
typedef typename CwiseBinaryOpImpl<
BinaryOp, Lhs, Rhs,
typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind,
BinaryOp, LhsType, RhsType,
typename internal::promote_storage_type<typename internal::traits<LhsType>::StorageKind,
typename internal::traits<Rhs>::StorageKind>::ret>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
typedef typename internal::nested<Lhs>::type LhsNested;
typedef typename internal::nested<Rhs>::type RhsNested;
typedef typename internal::nested<LhsType>::type LhsNested;
typedef typename internal::nested<RhsType>::type RhsNested;
typedef typename internal::remove_reference<LhsNested>::type _LhsNested;
typedef typename internal::remove_reference<RhsNested>::type _RhsNested;
@ -157,6 +160,7 @@ class CwiseBinaryOp : internal::no_assignment_operator,
const BinaryOp m_functor;
};
#ifndef EIGEN_TEST_EVALUATORS
template<typename BinaryOp, typename Lhs, typename Rhs>
class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
: public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
@ -195,6 +199,16 @@ class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense>
derived().rhs().template packet<LoadMode>(index));
}
};
#else
// Generic API dispatcher
template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind>
class CwiseBinaryOpImpl
: public internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type
{
public:
typedef typename internal::generic_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base;
};
#endif
/** replaces \c *this by \c *this - \a other.
*

View File

@ -67,6 +67,7 @@ class CwiseUnaryOp : internal::no_assignment_operator,
typedef typename CwiseUnaryOpImpl<UnaryOp, XprType,typename internal::traits<XprType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp)
typedef typename internal::remove_all<XprType>::type NestedExpression;
EIGEN_DEVICE_FUNC
inline CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp())
@ -96,6 +97,7 @@ class CwiseUnaryOp : internal::no_assignment_operator,
const UnaryOp m_functor;
};
#ifndef EIGEN_TEST_EVALUATORS
// This is the generic implementation for dense storage.
// It can be used for any expression types implementing the dense concept.
template<typename UnaryOp, typename XprType>
@ -107,7 +109,7 @@ class CwiseUnaryOpImpl<UnaryOp,XprType,Dense>
typedef CwiseUnaryOp<UnaryOp, XprType> Derived;
typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const Scalar coeff(Index rowId, Index colId) const
{
@ -133,6 +135,16 @@ class CwiseUnaryOpImpl<UnaryOp,XprType,Dense>
return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(index));
}
};
#else
// Generic API dispatcher
template<typename UnaryOp, typename XprType, typename StorageKind>
class CwiseUnaryOpImpl
: public internal::generic_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type
{
public:
typedef typename internal::generic_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base;
};
#endif
} // end namespace Eigen

View File

@ -66,6 +66,7 @@ class CwiseUnaryView : public CwiseUnaryViewImpl<ViewOp, MatrixType, typename in
typedef typename CwiseUnaryViewImpl<ViewOp, MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryView)
typedef typename internal::remove_all<MatrixType>::type NestedExpression;
inline CwiseUnaryView(const MatrixType& mat, const ViewOp& func = ViewOp())
: m_matrix(mat), m_functor(func) {}
@ -104,8 +105,8 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(CwiseUnaryViewImpl)
inline Scalar* data() { return &coeffRef(0); }
inline const Scalar* data() const { return &coeff(0); }
inline Scalar* data() { return &(this->coeffRef(0)); }
inline const Scalar* data() const { return &(this->coeff(0)); }
inline Index innerStride() const
{
@ -116,6 +117,8 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
{
return derived().nestedExpression().outerStride() * sizeof(typename internal::traits<MatrixType>::Scalar) / sizeof(Scalar);
}
#ifndef EIGEN_TEST_EVALUATORS
EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
{
@ -136,6 +139,8 @@ class CwiseUnaryViewImpl<ViewOp,MatrixType,Dense>
{
return derived().functor()(const_cast_derived().nestedExpression().coeffRef(index));
}
#endif
};
} // end namespace Eigen

View File

@ -74,6 +74,7 @@ template<typename Derived> class DenseBase
using Base::colIndexByOuterInner;
using Base::coeff;
using Base::coeffByOuterInner;
#ifndef EIGEN_TEST_EVALUATORS
using Base::packet;
using Base::packetByOuterInner;
using Base::writePacket;
@ -84,6 +85,7 @@ template<typename Derived> class DenseBase
using Base::copyCoeffByOuterInner;
using Base::copyPacket;
using Base::copyPacketByOuterInner;
#endif
using Base::operator();
using Base::operator[];
using Base::x;
@ -280,7 +282,8 @@ template<typename Derived> class DenseBase
Derived& operator=(const ReturnByValue<OtherDerived>& func);
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
/** Copies \a other into *this without evaluating other. \returns a reference to *this.
* \deprecated */
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
Derived& lazyAssign(const DenseBase<OtherDerived>& other);

View File

@ -97,8 +97,12 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const
{
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
&& col >= 0 && col < cols());
#ifndef EIGEN_TEST_EVALUATORS
return derived().coeff(row, col);
#else
return typename internal::evaluator<Derived>::type(derived()).coeff(row,col);
#endif
}
EIGEN_DEVICE_FUNC
@ -117,7 +121,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
{
eigen_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return derived().coeff(row, col);
return coeff(row, col);
}
/** Short version: don't use this function, use
@ -140,7 +144,11 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
coeff(Index index) const
{
eigen_internal_assert(index >= 0 && index < size());
#ifndef EIGEN_TEST_EVALUATORS
return derived().coeff(index);
#else
return typename internal::evaluator<Derived>::type(derived()).coeff(index);
#endif
}
@ -161,7 +169,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
#endif
eigen_assert(index >= 0 && index < size());
return derived().coeff(index);
return coeff(index);
}
/** \returns the coefficient at given index.
@ -179,7 +187,7 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
operator()(Index index) const
{
eigen_assert(index >= 0 && index < size());
return derived().coeff(index);
return coeff(index);
}
/** equivalent to operator[](0). */
@ -219,9 +227,12 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
template<int LoadMode>
EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const
{
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
eigen_internal_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
#ifndef EIGEN_TEST_EVALUATORS
return derived().template packet<LoadMode>(row,col);
#else
return typename internal::evaluator<Derived>::type(derived()).template packet<LoadMode>(row,col);
#endif
}
@ -247,7 +258,11 @@ class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived>
EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
{
eigen_internal_assert(index >= 0 && index < size());
#ifndef EIGEN_TEST_EVALUATORS
return derived().template packet<LoadMode>(index);
#else
return typename internal::evaluator<Derived>::type(derived()).template packet<LoadMode>(index);
#endif
}
protected:
@ -327,8 +342,12 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
{
eigen_internal_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
&& col >= 0 && col < cols());
#ifndef EIGEN_TEST_EVALUATORS
return derived().coeffRef(row, col);
#else
return typename internal::evaluator<Derived>::type(derived()).coeffRef(row,col);
#endif
}
EIGEN_DEVICE_FUNC
@ -350,7 +369,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
{
eigen_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return derived().coeffRef(row, col);
return coeffRef(row, col);
}
@ -374,7 +393,11 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
coeffRef(Index index)
{
eigen_internal_assert(index >= 0 && index < size());
#ifndef EIGEN_TEST_EVALUATORS
return derived().coeffRef(index);
#else
return typename internal::evaluator<Derived>::type(derived()).coeffRef(index);
#endif
}
/** \returns a reference to the coefficient at given index.
@ -393,7 +416,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
#endif
eigen_assert(index >= 0 && index < size());
return derived().coeffRef(index);
return coeffRef(index);
}
/** \returns a reference to the coefficient at given index.
@ -410,7 +433,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
operator()(Index index)
{
eigen_assert(index >= 0 && index < size());
return derived().coeffRef(index);
return coeffRef(index);
}
/** equivalent to operator[](0). */
@ -437,6 +460,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
EIGEN_STRONG_INLINE Scalar&
w() { return (*this)[3]; }
#ifndef EIGEN_TEST_EVALUATORS
/** \internal
* Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility
* to ensure that a packet really starts there. This method is only available on expressions having the
@ -573,6 +597,7 @@ class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived,
derived().template copyPacket< OtherDerived, StoreMode, LoadMode>(row, col, other);
}
#endif
#endif // EIGEN_TEST_EVALUATORS
};

View File

@ -81,6 +81,7 @@ public:
typedef MatrixBase<Derived> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
typedef typename internal::remove_all<XprType>::type NestedExpression;
private:
@ -101,19 +102,19 @@ namespace internal {
* \sa class Inverse
*/
template<typename XprType>
struct evaluator<Inverse<XprType> >
struct unary_evaluator<Inverse<XprType> >
: public evaluator<typename Inverse<XprType>::PlainObject>::type
{
typedef Inverse<XprType> InverseType;
typedef typename InverseType::PlainObject PlainObject;
typedef typename evaluator<PlainObject>::type Base;
typedef evaluator type;
typedef evaluator nestedType;
typedef evaluator<XprType> type;
typedef evaluator<XprType> nestedType;
enum { Flags = Base::Flags | EvalBeforeNestingBit };
evaluator(const InverseType& inv_xpr)
unary_evaluator(const InverseType& inv_xpr)
: m_result(inv_xpr.rows(), inv_xpr.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);

View File

@ -74,6 +74,7 @@ template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
typedef typename internal::dense_xpr_base<Replicate>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Replicate)
typedef typename internal::remove_all<MatrixType>::type NestedExpression;
template<typename OriginalMatrixType>
inline explicit Replicate(const OriginalMatrixType& a_matrix)

View File

@ -92,6 +92,34 @@ Derived& DenseBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
return derived();
}
#ifdef EIGEN_TEST_EVALUATORS
namespace internal {
template<typename Derived>
struct evaluator<ReturnByValue<Derived> >
: public evaluator<typename internal::traits<Derived>::ReturnType>::type
{
typedef ReturnByValue<Derived> XprType;
typedef typename internal::traits<Derived>::ReturnType PlainObject;
typedef typename evaluator<PlainObject>::type Base;
typedef evaluator type;
typedef evaluator nestedType;
evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols())
{
::new (static_cast<Base*>(this)) Base(m_result);
xpr.evalTo(m_result);
}
protected:
PlainObject m_result;
};
} // end namespace internal
#endif
} // end namespace Eigen
#endif // EIGEN_RETURNBYVALUE_H

View File

@ -77,6 +77,7 @@ template<typename MatrixType, int Direction> class Reverse
typedef typename internal::dense_xpr_base<Reverse>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
typedef typename internal::remove_all<MatrixType>::type NestedExpression;
using Base::IsRowMajor;
// next line is necessary because otherwise const version of operator()

View File

@ -68,6 +68,7 @@ template<typename MatrixType> class Transpose
typedef typename TransposeImpl<MatrixType,typename internal::traits<MatrixType>::StorageKind>::Base Base;
EIGEN_GENERIC_PUBLIC_INTERFACE(Transpose)
typedef typename internal::remove_all<MatrixType>::type NestedExpression;
EIGEN_DEVICE_FUNC
inline Transpose(MatrixType& a_matrix) : m_matrix(a_matrix) {}
@ -113,6 +114,7 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
public:
typedef typename internal::TransposeImpl_base<MatrixType>::type Base;
using Base::coeffRef;
EIGEN_DENSE_PUBLIC_INTERFACE(Transpose<MatrixType>)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TransposeImpl)
@ -127,6 +129,8 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
inline ScalarWithConstIfNotLvalue* data() { return derived().nestedExpression().data(); }
inline const Scalar* data() const { return derived().nestedExpression().data(); }
#ifndef EIGEN_TEST_EVALUATORS
EIGEN_DEVICE_FUNC
inline ScalarWithConstIfNotLvalue& coeffRef(Index rowId, Index colId)
@ -142,18 +146,6 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
return derived().nestedExpression().const_cast_derived().coeffRef(index);
}
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index rowId, Index colId) const
{
return derived().nestedExpression().coeffRef(colId, rowId);
}
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const
{
return derived().nestedExpression().coeffRef(index);
}
EIGEN_DEVICE_FUNC
inline CoeffReturnType coeff(Index rowId, Index colId) const
{
@ -189,6 +181,20 @@ template<typename MatrixType> class TransposeImpl<MatrixType,Dense>
{
derived().nestedExpression().const_cast_derived().template writePacket<LoadMode>(index, x);
}
#endif
// FIXME: shall we keep the const version of coeffRef?
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index rowId, Index colId) const
{
return derived().nestedExpression().coeffRef(colId, rowId);
}
EIGEN_DEVICE_FUNC
inline const Scalar& coeffRef(Index index) const
{
return derived().nestedExpression().coeffRef(index);
}
};
/** \returns an expression of the transpose of *this.

View File

@ -1071,8 +1071,8 @@ struct evaluator_traits<TriangularView<MatrixType,Mode> >
static const int AssumeAliasing = 0;
};
template<typename MatrixType, unsigned int Mode, typename Kind>
struct evaluator<TriangularView<MatrixType,Mode>, Kind, typename MatrixType::Scalar>
template<typename MatrixType, unsigned int Mode>
struct evaluator<TriangularView<MatrixType,Mode> >
: evaluator<typename internal::remove_all<MatrixType>::type>
{
typedef TriangularView<MatrixType,Mode> XprType;

View File

@ -219,8 +219,8 @@ struct gemm_functor
cols = m_rhs.cols();
Gemm::run(rows, cols, m_lhs.cols(),
/*(const Scalar*)*/&m_lhs.coeffRef(row,0), m_lhs.outerStride(),
/*(const Scalar*)*/&m_rhs.coeffRef(0,col), m_rhs.outerStride(),
&m_lhs.coeffRef(row,0), m_lhs.outerStride(),
&m_rhs.coeffRef(0,col), m_rhs.outerStride(),
(Scalar*)&(m_dest.coeffRef(row,col)), m_dest.outerStride(),
m_actualAlpha, m_blocking, info);
}

View File

@ -38,9 +38,7 @@ template<typename Derived> struct accessors_level
template<typename T> struct evaluator_traits;
template< typename T,
typename Kind = typename evaluator_traits<T>::Kind,
typename Scalar = typename T::Scalar> struct evaluator;
template< typename T> struct evaluator;
} // end namespace internal

View File

@ -465,6 +465,15 @@ struct dense_xpr_base<Derived, ArrayXpr>
typedef ArrayBase<Derived> type;
};
template<typename Derived, typename XprKind = typename traits<Derived>::XprKind, typename StorageKind = typename traits<Derived>::StorageKind>
struct generic_xpr_base;
template<typename Derived, typename XprKind>
struct generic_xpr_base<Derived, XprKind, Dense>
{
typedef typename dense_xpr_base<Derived,XprKind>::type type;
};
/** \internal Helper base class to add a scalar multiple operator
* overloads for complex types */
template<typename Derived,typename Scalar,typename OtherScalar,