diff options
Diffstat (limited to 'third_party/eigen3/Eigen/src/Core/CoreEvaluators.h')
-rw-r--r-- | third_party/eigen3/Eigen/src/Core/CoreEvaluators.h | 1121 |
1 files changed, 1121 insertions, 0 deletions
diff --git a/third_party/eigen3/Eigen/src/Core/CoreEvaluators.h b/third_party/eigen3/Eigen/src/Core/CoreEvaluators.h new file mode 100644 index 0000000000..3568cb85f9 --- /dev/null +++ b/third_party/eigen3/Eigen/src/Core/CoreEvaluators.h @@ -0,0 +1,1121 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com> +// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr> +// Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk> +// +// 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 +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +#ifndef EIGEN_COREEVALUATORS_H +#define EIGEN_COREEVALUATORS_H + +namespace Eigen { + +namespace internal { + +// evaluator_traits<T> contains traits for evaluator_impl<T> + +template<typename T> +struct evaluator_traits +{ + // 1 if evaluator_impl<T>::evalTo() exists + // 0 if evaluator_impl<T> allows coefficient-based access + static const int HasEvalTo = 0; + + // 1 if assignment A = B assumes aliasing when B is of type T and thus B needs to be evaluated into a + // temporary; 0 if not. + static const int AssumeAliasing = 0; +}; + +// expression class for evaluating nested expression to a temporary + +template<typename ArgType> +class EvalToTemp; + +// evaluator<T>::type is type of evaluator for T +// evaluator<T>::nestedType is type of evaluator if T is nested inside another evaluator + +template<typename T> +struct evaluator_impl +{ }; + +template<typename T, int Nested = evaluator_traits<T>::HasEvalTo> +struct evaluator_nested_type; + +template<typename T> +struct evaluator_nested_type<T, 0> +{ + typedef evaluator_impl<T> type; +}; + +template<typename T> +struct evaluator_nested_type<T, 1> +{ + typedef evaluator_impl<EvalToTemp<T> > type; +}; + +template<typename T> +struct evaluator +{ + typedef evaluator_impl<T> type; + typedef typename evaluator_nested_type<T>::type nestedType; +}; + +// TODO: Think about const-correctness + +template<typename T> +struct evaluator<const T> + : evaluator<T> +{ }; + +// ---------- base class for all writable evaluators ---------- + +// TODO this class does not seem to be necessary anymore +template<typename ExpressionType> +struct evaluator_impl_base +{ + typedef typename ExpressionType::Index Index; + // TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices. + typedef traits<ExpressionType> ExpressionTraits; + + evaluator_impl<ExpressionType>& derived() + { + return *static_cast<evaluator_impl<ExpressionType>*>(this); + } +}; + +// -------------------- Matrix and Array -------------------- +// +// evaluator_impl<PlainObjectBase> is a common base class for the +// Matrix and Array evaluators. + +template<typename Derived> +struct evaluator_impl<PlainObjectBase<Derived> > + : evaluator_impl_base<Derived> +{ + typedef PlainObjectBase<Derived> PlainObjectType; + + enum { + IsRowMajor = PlainObjectType::IsRowMajor, + IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime, + RowsAtCompileTime = PlainObjectType::RowsAtCompileTime, + ColsAtCompileTime = PlainObjectType::ColsAtCompileTime + }; + + evaluator_impl(const PlainObjectType& m) + : 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) + return m_data[row * m_outerStride.value() + col]; + else + return m_data[row + col * m_outerStride.value()]; + } + + CoeffReturnType coeff(Index index) const + { + return m_data[index]; + } + + Scalar& coeffRef(Index row, Index col) + { + if (IsRowMajor) + return const_cast<Scalar*>(m_data)[row * m_outerStride.value() + col]; + else + return const_cast<Scalar*>(m_data)[row + col * m_outerStride.value()]; + } + + Scalar& coeffRef(Index index) + { + return const_cast<Scalar*>(m_data)[index]; + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + if (IsRowMajor) + return ploadt<PacketScalar, LoadMode>(m_data + row * m_outerStride.value() + col); + else + return ploadt<PacketScalar, LoadMode>(m_data + row + col * m_outerStride.value()); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return ploadt<PacketScalar, LoadMode>(m_data + index); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + if (IsRowMajor) + return pstoret<Scalar, PacketScalar, StoreMode> + (const_cast<Scalar*>(m_data) + row * m_outerStride.value() + col, x); + else + return pstoret<Scalar, PacketScalar, StoreMode> + (const_cast<Scalar*>(m_data) + row + col * m_outerStride.value(), x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + return pstoret<Scalar, PacketScalar, StoreMode>(const_cast<Scalar*>(m_data) + index, x); + } + +protected: + const Scalar *m_data; + + // We do not need to know the outer stride for vectors + variable_if_dynamic<Index, IsVectorAtCompileTime ? 0 + : int(IsRowMajor) ? ColsAtCompileTime + : RowsAtCompileTime> m_outerStride; +}; + +template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> +struct evaluator_impl<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > + : evaluator_impl<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > > +{ + typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType; + + evaluator_impl(const XprType& m) + : evaluator_impl<PlainObjectBase<XprType> >(m) + { } +}; + +template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols> +struct evaluator_impl<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > + : evaluator_impl<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > > +{ + typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType; + + evaluator_impl(const XprType& m) + : evaluator_impl<PlainObjectBase<XprType> >(m) + { } +}; + +// -------------------- 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_impl<EvalToTemp<ArgType> > +{ + typedef EvalToTemp<ArgType> XprType; + typedef typename ArgType::PlainObject PlainObject; + + evaluator_impl(const XprType& xpr) + : m_result(xpr.rows(), xpr.cols()), m_resultImpl(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_impl(const ArgType& arg) + : m_result(arg.rows(), arg.cols()), m_resultImpl(m_result) + { + // TODO we should simply do m_result(xpr.arg()); + call_dense_assignment_loop(m_result, arg); + } + + typedef typename PlainObject::Index Index; + typedef typename PlainObject::Scalar Scalar; + typedef typename PlainObject::CoeffReturnType CoeffReturnType; + typedef typename PlainObject::PacketScalar PacketScalar; + typedef typename PlainObject::PacketReturnType PacketReturnType; + + // All other functions are forwarded to m_resultImpl + + CoeffReturnType coeff(Index row, Index col) const + { + return m_resultImpl.coeff(row, col); + } + + CoeffReturnType coeff(Index index) const + { + return m_resultImpl.coeff(index); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_resultImpl.coeffRef(row, col); + } + + Scalar& coeffRef(Index index) + { + return m_resultImpl.coeffRef(index); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + return m_resultImpl.template packet<LoadMode>(row, col); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return m_resultImpl.packet<LoadMode>(index); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + m_resultImpl.template writePacket<StoreMode>(row, col, x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + m_resultImpl.template writePacket<StoreMode>(index, x); + } + +protected: + PlainObject m_result; + typename evaluator<PlainObject>::nestedType m_resultImpl; +}; + +// -------------------- Transpose -------------------- + +template<typename ArgType> +struct evaluator_impl<Transpose<ArgType> > + : evaluator_impl_base<Transpose<ArgType> > +{ + typedef Transpose<ArgType> XprType; + + evaluator_impl(const XprType& t) : m_argImpl(t.nestedExpression()) {} + + 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; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_argImpl.coeff(col, row); + } + + CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(index); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_argImpl.coeffRef(col, row); + } + + typename XprType::Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(index); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + return m_argImpl.template packet<LoadMode>(col, row); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return m_argImpl.template packet<LoadMode>(index); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + m_argImpl.template writePacket<StoreMode>(col, row, x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + m_argImpl.template writePacket<StoreMode>(index, x); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; +}; + +// -------------------- CwiseNullaryOp -------------------- + +template<typename NullaryOp, typename PlainObjectType> +struct evaluator_impl<CwiseNullaryOp<NullaryOp,PlainObjectType> > +{ + typedef CwiseNullaryOp<NullaryOp,PlainObjectType> XprType; + + evaluator_impl(const XprType& n) + : m_functor(n.functor()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::CoeffReturnType CoeffReturnType; + typedef typename XprType::PacketScalar PacketScalar; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_functor(row, col); + } + + CoeffReturnType coeff(Index index) const + { + return m_functor(index); + } + + template<int LoadMode> + PacketScalar packet(Index row, Index col) const + { + return m_functor.packetOp(row, col); + } + + template<int LoadMode> + PacketScalar packet(Index index) const + { + return m_functor.packetOp(index); + } + +protected: + const NullaryOp m_functor; +}; + +// -------------------- CwiseUnaryOp -------------------- + +template<typename UnaryOp, typename ArgType> +struct evaluator_impl<CwiseUnaryOp<UnaryOp, ArgType> > +{ + typedef CwiseUnaryOp<UnaryOp, ArgType> XprType; + + evaluator_impl(const XprType& op) + : m_functor(op.functor()), + m_argImpl(op.nestedExpression()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::CoeffReturnType CoeffReturnType; + typedef typename XprType::PacketScalar PacketScalar; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_functor(m_argImpl.coeff(row, col)); + } + + CoeffReturnType coeff(Index index) const + { + return m_functor(m_argImpl.coeff(index)); + } + + template<int LoadMode> + PacketScalar packet(Index row, Index col) const + { + return m_functor.packetOp(m_argImpl.template packet<LoadMode>(row, col)); + } + + template<int LoadMode> + PacketScalar packet(Index index) const + { + return m_functor.packetOp(m_argImpl.template packet<LoadMode>(index)); + } + +protected: + const UnaryOp m_functor; + typename evaluator<ArgType>::nestedType m_argImpl; +}; + +// -------------------- CwiseBinaryOp -------------------- + +template<typename BinaryOp, typename Lhs, typename Rhs> +struct evaluator_impl<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > +{ + typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType; + + evaluator_impl(const XprType& xpr) + : m_functor(xpr.functor()), + m_lhsImpl(xpr.lhs()), + m_rhsImpl(xpr.rhs()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::CoeffReturnType CoeffReturnType; + typedef typename XprType::PacketScalar PacketScalar; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col)); + } + + CoeffReturnType coeff(Index index) const + { + return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index)); + } + + template<int LoadMode> + PacketScalar packet(Index row, Index col) const + { + return m_functor.packetOp(m_lhsImpl.template packet<LoadMode>(row, col), + m_rhsImpl.template packet<LoadMode>(row, col)); + } + + template<int LoadMode> + PacketScalar packet(Index index) const + { + return m_functor.packetOp(m_lhsImpl.template packet<LoadMode>(index), + m_rhsImpl.template packet<LoadMode>(index)); + } + +protected: + const BinaryOp m_functor; + typename evaluator<Lhs>::nestedType m_lhsImpl; + typename evaluator<Rhs>::nestedType m_rhsImpl; +}; + +// -------------------- CwiseUnaryView -------------------- + +template<typename UnaryOp, typename ArgType> +struct evaluator_impl<CwiseUnaryView<UnaryOp, ArgType> > + : evaluator_impl_base<CwiseUnaryView<UnaryOp, ArgType> > +{ + typedef CwiseUnaryView<UnaryOp, ArgType> XprType; + + evaluator_impl(const XprType& op) + : m_unaryOp(op.functor()), + m_argImpl(op.nestedExpression()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_unaryOp(m_argImpl.coeff(row, col)); + } + + CoeffReturnType coeff(Index index) const + { + return m_unaryOp(m_argImpl.coeff(index)); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_unaryOp(m_argImpl.coeffRef(row, col)); + } + + Scalar& coeffRef(Index index) + { + return m_unaryOp(m_argImpl.coeffRef(index)); + } + +protected: + const UnaryOp m_unaryOp; + typename evaluator<ArgType>::nestedType m_argImpl; +}; + +// -------------------- Map -------------------- + +template<typename Derived, int AccessorsType> +struct evaluator_impl<MapBase<Derived, AccessorsType> > + : evaluator_impl_base<Derived> +{ + typedef MapBase<Derived, AccessorsType> MapType; + typedef Derived XprType; + + typedef typename XprType::PointerType PointerType; + 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; + + evaluator_impl(const XprType& map) + : m_data(const_cast<PointerType>(map.data())), + m_rowStride(map.rowStride()), + m_colStride(map.colStride()) + { } + + enum { + RowsAtCompileTime = XprType::RowsAtCompileTime + }; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_data[col * m_colStride + row * m_rowStride]; + } + + CoeffReturnType coeff(Index index) const + { + return coeff(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_data[col * m_colStride + row * m_rowStride]; + } + + Scalar& coeffRef(Index index) + { + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + PointerType ptr = m_data + row * m_rowStride + col * m_colStride; + return internal::ploadt<PacketScalar, LoadMode>(ptr); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return packet<LoadMode>(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + PointerType ptr = m_data + row * m_rowStride + col * m_colStride; + return internal::pstoret<Scalar, PacketScalar, StoreMode>(ptr, x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + return writePacket<StoreMode>(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, + x); + } + +protected: + PointerType m_data; + int m_rowStride; + int m_colStride; +}; + +template<typename PlainObjectType, int MapOptions, typename StrideType> +struct evaluator_impl<Map<PlainObjectType, MapOptions, StrideType> > + : public evaluator_impl<MapBase<Map<PlainObjectType, MapOptions, StrideType> > > +{ + typedef Map<PlainObjectType, MapOptions, StrideType> XprType; + + evaluator_impl(const XprType& map) + : evaluator_impl<MapBase<XprType> >(map) + { } +}; + +// -------------------- Block -------------------- + +template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel, + bool HasDirectAccess = internal::has_direct_access<ArgType>::ret> struct block_evaluator; + +template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> +struct evaluator_impl<Block<ArgType, BlockRows, BlockCols, InnerPanel> > + : block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> +{ + typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType; + typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> block_evaluator_type; + evaluator_impl(const XprType& block) : block_evaluator_type(block) {} +}; + +template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> +struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAccess*/ false> + : evaluator_impl_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> > +{ + typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType; + + block_evaluator(const XprType& block) + : m_argImpl(block.nestedExpression()), + m_startRow(block.startRow()), + m_startCol(block.startCol()) + { } + + 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; + + enum { + RowsAtCompileTime = XprType::RowsAtCompileTime + }; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col); + } + + CoeffReturnType coeff(Index index) const + { + return coeff(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col); + } + + Scalar& coeffRef(Index index) + { + return coeffRef(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + return m_argImpl.template packet<LoadMode>(m_startRow.value() + row, m_startCol.value() + col); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return packet<LoadMode>(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + return m_argImpl.template writePacket<StoreMode>(m_startRow.value() + row, m_startCol.value() + col, x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + return writePacket<StoreMode>(RowsAtCompileTime == 1 ? 0 : index, + RowsAtCompileTime == 1 ? index : 0, + x); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; + const variable_if_dynamic<Index, ArgType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow; + const variable_if_dynamic<Index, ArgType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol; +}; + +// TODO: This evaluator does not actually use the child evaluator; +// all action is via the data() as returned by the Block expression. + +template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> +struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true> + : evaluator_impl<MapBase<Block<ArgType, BlockRows, BlockCols, InnerPanel> > > +{ + typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType; + + block_evaluator(const XprType& block) + : evaluator_impl<MapBase<XprType> >(block) + { } +}; + + +// -------------------- Select -------------------- + +template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> +struct evaluator_impl<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> > +{ + typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType; + + evaluator_impl(const XprType& select) + : m_conditionImpl(select.conditionMatrix()), + m_thenImpl(select.thenMatrix()), + m_elseImpl(select.elseMatrix()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + CoeffReturnType coeff(Index row, Index col) const + { + if (m_conditionImpl.coeff(row, col)) + return m_thenImpl.coeff(row, col); + else + return m_elseImpl.coeff(row, col); + } + + CoeffReturnType coeff(Index index) const + { + if (m_conditionImpl.coeff(index)) + return m_thenImpl.coeff(index); + else + return m_elseImpl.coeff(index); + } + +protected: + typename evaluator<ConditionMatrixType>::nestedType m_conditionImpl; + typename evaluator<ThenMatrixType>::nestedType m_thenImpl; + typename evaluator<ElseMatrixType>::nestedType m_elseImpl; +}; + + +// -------------------- Replicate -------------------- + +template<typename ArgType, int RowFactor, int ColFactor> +struct evaluator_impl<Replicate<ArgType, RowFactor, ColFactor> > +{ + typedef Replicate<ArgType, RowFactor, ColFactor> XprType; + + evaluator_impl(const XprType& replicate) + : m_argImpl(replicate.nestedExpression()), + m_rows(replicate.nestedExpression().rows()), + 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 + const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0 + : RowFactor==1 ? row + : row % m_rows.value(); + const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0 + : ColFactor==1 ? col + : col % m_cols.value(); + + return m_argImpl.coeff(actual_row, actual_col); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0 + : RowFactor==1 ? row + : row % m_rows.value(); + const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0 + : ColFactor==1 ? col + : col % m_cols.value(); + + return m_argImpl.template packet<LoadMode>(actual_row, actual_col); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; + const variable_if_dynamic<Index, XprType::RowsAtCompileTime> m_rows; + const variable_if_dynamic<Index, XprType::ColsAtCompileTime> m_cols; +}; + + +// -------------------- PartialReduxExpr -------------------- +// +// This is a wrapper around the expression object. +// TODO: Find out how to write a proper evaluator without duplicating +// the row() and col() member functions. + +template< typename ArgType, typename MemberOp, int Direction> +struct evaluator_impl<PartialReduxExpr<ArgType, MemberOp, Direction> > +{ + typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType; + + evaluator_impl(const XprType expr) + : m_expr(expr) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_expr.coeff(row, col); + } + + CoeffReturnType coeff(Index index) const + { + return m_expr.coeff(index); + } + +protected: + const XprType m_expr; +}; + + +// -------------------- MatrixWrapper and ArrayWrapper -------------------- +// +// evaluator_impl_wrapper_base<T> is a common base class for the +// MatrixWrapper and ArrayWrapper evaluators. + +template<typename XprType> +struct evaluator_impl_wrapper_base + : evaluator_impl_base<XprType> +{ + typedef typename remove_all<typename XprType::NestedExpressionType>::type ArgType; + + evaluator_impl_wrapper_base(const ArgType& arg) : m_argImpl(arg) {} + + typedef typename ArgType::Index Index; + typedef typename ArgType::Scalar Scalar; + typedef typename ArgType::CoeffReturnType CoeffReturnType; + typedef typename ArgType::PacketScalar PacketScalar; + typedef typename ArgType::PacketReturnType PacketReturnType; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_argImpl.coeff(row, col); + } + + CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(index); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_argImpl.coeffRef(row, col); + } + + Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(index); + } + + template<int LoadMode> + PacketReturnType packet(Index row, Index col) const + { + return m_argImpl.template packet<LoadMode>(row, col); + } + + template<int LoadMode> + PacketReturnType packet(Index index) const + { + return m_argImpl.template packet<LoadMode>(index); + } + + template<int StoreMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + m_argImpl.template writePacket<StoreMode>(row, col, x); + } + + template<int StoreMode> + void writePacket(Index index, const PacketScalar& x) + { + m_argImpl.template writePacket<StoreMode>(index, x); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; +}; + +template<typename TArgType> +struct evaluator_impl<MatrixWrapper<TArgType> > + : evaluator_impl_wrapper_base<MatrixWrapper<TArgType> > +{ + typedef MatrixWrapper<TArgType> XprType; + + evaluator_impl(const XprType& wrapper) + : evaluator_impl_wrapper_base<MatrixWrapper<TArgType> >(wrapper.nestedExpression()) + { } +}; + +template<typename TArgType> +struct evaluator_impl<ArrayWrapper<TArgType> > + : evaluator_impl_wrapper_base<ArrayWrapper<TArgType> > +{ + typedef ArrayWrapper<TArgType> XprType; + + evaluator_impl(const XprType& wrapper) + : evaluator_impl_wrapper_base<ArrayWrapper<TArgType> >(wrapper.nestedExpression()) + { } +}; + + +// -------------------- Reverse -------------------- + +// defined in Reverse.h: +template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond; + +template<typename ArgType, int Direction> +struct evaluator_impl<Reverse<ArgType, Direction> > + : evaluator_impl_base<Reverse<ArgType, Direction> > +{ + typedef Reverse<ArgType, Direction> XprType; + 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; + + enum { + PacketSize = internal::packet_traits<Scalar>::size, + IsRowMajor = XprType::IsRowMajor, + IsColMajor = !IsRowMajor, + ReverseRow = (Direction == Vertical) || (Direction == BothDirections), + ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), + OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1, + OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, + ReversePacket = (Direction == BothDirections) + || ((Direction == Vertical) && IsColMajor) + || ((Direction == Horizontal) && IsRowMajor) + }; + typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet; + + evaluator_impl(const XprType& reverse) + : m_argImpl(reverse.nestedExpression()), + m_rows(ReverseRow ? reverse.nestedExpression().rows() : 0), + m_cols(ReverseCol ? reverse.nestedExpression().cols() : 0) + { } + + CoeffReturnType coeff(Index row, Index col) const + { + return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row, + ReverseCol ? m_cols.value() - col - 1 : col); + } + + CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row, + ReverseCol ? m_cols.value() - col - 1 : col); + } + + Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1); + } + + template<int LoadMode> + PacketScalar packet(Index row, Index col) const + { + return reverse_packet::run(m_argImpl.template packet<LoadMode>( + ReverseRow ? m_rows.value() - row - OffsetRow : row, + ReverseCol ? m_cols.value() - col - OffsetCol : col)); + } + + template<int LoadMode> + PacketScalar packet(Index index) const + { + return preverse(m_argImpl.template packet<LoadMode>(m_rows.value() * m_cols.value() - index - PacketSize)); + } + + template<int LoadMode> + void writePacket(Index row, Index col, const PacketScalar& x) + { + m_argImpl.template writePacket<LoadMode>( + ReverseRow ? m_rows.value() - row - OffsetRow : row, + ReverseCol ? m_cols.value() - col - OffsetCol : col, + reverse_packet::run(x)); + } + + template<int LoadMode> + void writePacket(Index index, const PacketScalar& x) + { + m_argImpl.template writePacket<LoadMode> + (m_rows.value() * m_cols.value() - index - PacketSize, preverse(x)); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; + + // If we do not reverse rows, then we do not need to know the number of rows; same for columns + const variable_if_dynamic<Index, ReverseRow ? ArgType::RowsAtCompileTime : 0> m_rows; + const variable_if_dynamic<Index, ReverseCol ? ArgType::ColsAtCompileTime : 0> m_cols; +}; + + +// -------------------- Diagonal -------------------- + +template<typename ArgType, int DiagIndex> +struct evaluator_impl<Diagonal<ArgType, DiagIndex> > + : evaluator_impl_base<Diagonal<ArgType, DiagIndex> > +{ + typedef Diagonal<ArgType, DiagIndex> XprType; + + evaluator_impl(const XprType& diagonal) + : m_argImpl(diagonal.nestedExpression()), + m_index(diagonal.index()) + { } + + typedef typename XprType::Index Index; + typedef typename XprType::Scalar Scalar; + typedef typename XprType::CoeffReturnType CoeffReturnType; + + CoeffReturnType coeff(Index row, Index) const + { + return m_argImpl.coeff(row + rowOffset(), row + colOffset()); + } + + CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(index + rowOffset(), index + colOffset()); + } + + Scalar& coeffRef(Index row, Index) + { + return m_argImpl.coeffRef(row + rowOffset(), row + colOffset()); + } + + Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(index + rowOffset(), index + colOffset()); + } + +protected: + typename evaluator<ArgType>::nestedType m_argImpl; + const internal::variable_if_dynamicindex<Index, XprType::DiagIndex> m_index; + +private: + EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); } + EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; } +}; + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_COREEVALUATORS_H |