// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2011 Benoit Jacob // Copyright (C) 2011 Gael Guennebaud // Copyright (C) 2011 Jitse Niesen // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // // Alternatively, you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License and a copy of the GNU General Public License along with // Eigen. If not, see . #ifndef EIGEN_COREEVALUATORS_H #define EIGEN_COREEVALUATORS_H namespace Eigen { namespace internal { // evaluator_traits contains traits for evaluator_impl template struct evaluator_traits { // 1 if evaluator_impl::evalTo() exists // 0 if evaluator_impl allows coefficient-based access static const int HasEvalTo = 0; }; // evaluator::type is type of evaluator for T template struct evaluator_impl {}; template struct evaluator { typedef evaluator_impl type; }; // TODO: Think about const-correctness template struct evaluator { typedef evaluator_impl type; }; // ---------- base class for all writable evaluators ---------- template struct evaluator_impl_base { typedef typename ExpressionType::Index Index; template void copyCoeff(Index row, Index col, const OtherEvaluatorType& other) { derived().coeffRef(row, col) = other.coeff(row, col); } template void copyCoeffByOuterInner(Index outer, Index inner, const OtherEvaluatorType& other) { Index row = rowIndexByOuterInner(outer, inner); Index col = colIndexByOuterInner(outer, inner); derived().copyCoeff(row, col, other); } template void copyCoeff(Index index, const OtherEvaluatorType& other) { derived().coeffRef(index) = other.coeff(index); } template void copyPacket(Index row, Index col, const OtherEvaluatorType& other) { derived().template writePacket(row, col, other.template packet(row, col)); } template void copyPacketByOuterInner(Index outer, Index inner, const OtherEvaluatorType& other) { Index row = rowIndexByOuterInner(outer, inner); Index col = colIndexByOuterInner(outer, inner); derived().template copyPacket(row, col, other); } template void copyPacket(Index index, const OtherEvaluatorType& other) { derived().template writePacket(index, other.template packet(index)); } Index rowIndexByOuterInner(Index outer, Index inner) const { return int(ExpressionType::RowsAtCompileTime) == 1 ? 0 : int(ExpressionType::ColsAtCompileTime) == 1 ? inner : int(ExpressionType::Flags)&RowMajorBit ? outer : inner; } Index colIndexByOuterInner(Index outer, Index inner) const { return int(ExpressionType::ColsAtCompileTime) == 1 ? 0 : int(ExpressionType::RowsAtCompileTime) == 1 ? inner : int(ExpressionType::Flags)&RowMajorBit ? inner : outer; } evaluator_impl& derived() { return *static_cast*>(this); } }; // -------------------- Transpose -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef Transpose 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 PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(col, row); } template PacketReturnType packet(Index index) const { return m_argImpl.template packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket(col, row, x); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket(index, x); } protected: typename evaluator::type m_argImpl; }; // -------------------- Matrix and Array -------------------- // // evaluator_impl is a common base class for the // Matrix and Array evaluators. template struct evaluator_impl > : evaluator_impl_base { typedef PlainObjectBase PlainObjectType; evaluator_impl(const PlainObjectType& m) : m_plainObject(m) {} 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 i, Index j) const { return m_plainObject.coeff(i, j); } CoeffReturnType coeff(Index index) const { return m_plainObject.coeff(index); } Scalar& coeffRef(Index i, Index j) { return m_plainObject.const_cast_derived().coeffRef(i, j); } Scalar& coeffRef(Index index) { return m_plainObject.const_cast_derived().coeffRef(index); } template PacketReturnType packet(Index row, Index col) const { return m_plainObject.template packet(row, col); } template PacketReturnType packet(Index index) const { return m_plainObject.template packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_plainObject.const_cast_derived().template writePacket(row, col, x); } template void writePacket(Index index, const PacketScalar& x) { m_plainObject.const_cast_derived().template writePacket(index, x); } protected: const PlainObjectType &m_plainObject; }; template struct evaluator_impl > : evaluator_impl > > { typedef Matrix XprType; evaluator_impl(const XprType& m) : evaluator_impl >(m) { } }; template struct evaluator_impl > : evaluator_impl > > { typedef Array XprType; evaluator_impl(const XprType& m) : evaluator_impl >(m) { } }; // -------------------- CwiseNullaryOp -------------------- template struct evaluator_impl > { typedef CwiseNullaryOp 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 PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(row, col); } template PacketScalar packet(Index index) const { return m_functor.packetOp(index); } protected: const NullaryOp m_functor; }; // -------------------- CwiseUnaryOp -------------------- template struct evaluator_impl > { typedef CwiseUnaryOp 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 PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(m_argImpl.template packet(row, col)); } template PacketScalar packet(Index index) const { return m_functor.packetOp(m_argImpl.template packet(index)); } protected: const UnaryOp m_functor; typename evaluator::type m_argImpl; }; // -------------------- CwiseBinaryOp -------------------- template struct evaluator_impl > { typedef CwiseBinaryOp 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 PacketScalar packet(Index row, Index col) const { return m_functor.packetOp(m_lhsImpl.template packet(row, col), m_rhsImpl.template packet(row, col)); } template PacketScalar packet(Index index) const { return m_functor.packetOp(m_lhsImpl.template packet(index), m_rhsImpl.template packet(index)); } protected: const BinaryOp m_functor; typename evaluator::type m_lhsImpl; typename evaluator::type m_rhsImpl; }; // -------------------- CwiseUnaryView -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef CwiseUnaryView 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::type m_argImpl; }; // -------------------- Map -------------------- template struct evaluator_impl > : evaluator_impl_base { typedef MapBase 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(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 PacketReturnType packet(Index row, Index col) const { PointerType ptr = m_data + row * m_rowStride + col * m_colStride; return internal::ploadt(ptr); } template PacketReturnType packet(Index index) const { return packet(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template void writePacket(Index row, Index col, const PacketScalar& x) { PointerType ptr = m_data + row * m_rowStride + col * m_colStride; return internal::pstoret(ptr, x); } template void writePacket(Index index, const PacketScalar& x) { return writePacket(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, x); } protected: PointerType m_data; int m_rowStride; int m_colStride; }; template struct evaluator_impl > : public evaluator_impl > > { typedef Map XprType; evaluator_impl(const XprType& map) : evaluator_impl >(map) { } }; // -------------------- Block -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef Block XprType; evaluator_impl(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 + row, m_startCol + 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 + row, m_startCol + col); } Scalar& coeffRef(Index index) { return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(m_startRow + row, m_startCol + col); } template PacketReturnType packet(Index index) const { return packet(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0); } template void writePacket(Index row, Index col, const PacketScalar& x) { return m_argImpl.template writePacket(m_startRow + row, m_startCol + col, x); } template void writePacket(Index index, const PacketScalar& x) { return writePacket(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0, x); } protected: typename evaluator::type m_argImpl; // TODO: Get rid of m_startRow, m_startCol if known at compile time Index m_startRow; Index 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 struct evaluator_impl > : evaluator_impl > > { typedef Block XprType; evaluator_impl(const XprType& block) : evaluator_impl >(block) { } }; // -------------------- Select -------------------- template struct evaluator_impl > { typedef Select 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::type m_conditionImpl; typename evaluator::type m_thenImpl; typename evaluator::type m_elseImpl; }; // -------------------- Replicate -------------------- template struct evaluator_impl > { typedef Replicate 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::RowsAtCompileTime==1 ? 0 : RowFactor==1 ? row : row % m_rows; const Index actual_col = internal::traits::ColsAtCompileTime==1 ? 0 : ColFactor==1 ? col : col % m_cols; return m_argImpl.coeff(actual_row, actual_col); } template PacketReturnType packet(Index row, Index col) const { const Index actual_row = internal::traits::RowsAtCompileTime==1 ? 0 : RowFactor==1 ? row : row % m_rows; const Index actual_col = internal::traits::ColsAtCompileTime==1 ? 0 : ColFactor==1 ? col : col % m_cols; return m_argImpl.template packet(actual_row, actual_col); } protected: typename evaluator::type m_argImpl; Index m_rows; // TODO: Get rid of this if known at compile time Index 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 > { typedef PartialReduxExpr 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 is a common base class for the // MatrixWrapper and ArrayWrapper evaluators. template struct evaluator_impl_wrapper_base : evaluator_impl_base { typedef typename remove_all::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 PacketReturnType packet(Index row, Index col) const { return m_argImpl.template packet(row, col); } template PacketReturnType packet(Index index) const { return m_argImpl.template packet(index); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket(row, col, x); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket(index, x); } protected: typename evaluator::type m_argImpl; }; template struct evaluator_impl > : evaluator_impl_wrapper_base > { typedef MatrixWrapper XprType; evaluator_impl(const XprType& wrapper) : evaluator_impl_wrapper_base >(wrapper.nestedExpression()) { } }; template struct evaluator_impl > : evaluator_impl_wrapper_base > { typedef ArrayWrapper XprType; evaluator_impl(const XprType& wrapper) : evaluator_impl_wrapper_base >(wrapper.nestedExpression()) { } }; // -------------------- Reverse -------------------- // defined in Reverse.h: template struct reverse_packet_cond; template struct evaluator_impl > : evaluator_impl_base > { typedef Reverse XprType; evaluator_impl(const XprType& reverse) : m_argImpl(reverse.nestedExpression()), m_rows(reverse.nestedExpression().rows()), m_cols(reverse.nestedExpression().cols()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::CoeffReturnType CoeffReturnType; typedef typename XprType::PacketScalar PacketScalar; typedef typename XprType::PacketReturnType PacketReturnType; enum { PacketSize = internal::packet_traits::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 reverse_packet; CoeffReturnType coeff(Index row, Index col) const { return m_argImpl.coeff(ReverseRow ? m_rows - row - 1 : row, ReverseCol ? m_cols - col - 1 : col); } CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(m_rows * m_cols - index - 1); } Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(ReverseRow ? m_rows - row - 1 : row, ReverseCol ? m_cols - col - 1 : col); } Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(m_rows * m_cols - index - 1); } template PacketScalar packet(Index row, Index col) const { return reverse_packet::run(m_argImpl.template packet( ReverseRow ? m_rows - row - OffsetRow : row, ReverseCol ? m_cols - col - OffsetCol : col)); } template PacketScalar packet(Index index) const { return preverse(m_argImpl.template packet(m_rows * m_cols - index - PacketSize)); } template void writePacket(Index row, Index col, const PacketScalar& x) { m_argImpl.template writePacket( ReverseRow ? m_rows - row - OffsetRow : row, ReverseCol ? m_cols - col - OffsetCol : col, reverse_packet::run(x)); } template void writePacket(Index index, const PacketScalar& x) { m_argImpl.template writePacket(m_rows * m_cols - index - PacketSize, preverse(x)); } protected: typename evaluator::type m_argImpl; Index m_rows; // TODO: Don't use if known at compile time or not needed Index m_cols; }; // -------------------- Diagonal -------------------- template struct evaluator_impl > : evaluator_impl_base > { typedef Diagonal 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::type m_argImpl; Index m_index; // TODO: Don't use if known at compile time private: EIGEN_STRONG_INLINE Index rowOffset() const { return m_index>0 ? 0 : -m_index; } EIGEN_STRONG_INLINE Index colOffset() const { return m_index>0 ? m_index : 0; } }; // ---------- SwapWrapper ---------- template struct evaluator_impl > : evaluator_impl_base > { typedef SwapWrapper XprType; evaluator_impl(const XprType& swapWrapper) : m_argImpl(swapWrapper.expression()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::Packet Packet; // This function and the next one are needed by assign to correctly align loads/stores // TODO make Assign use .data() Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(row, col); } inline Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } template void copyCoeff(Index row, Index col, const OtherEvaluatorType& other) { OtherEvaluatorType& nonconst_other = const_cast(other); Scalar tmp = m_argImpl.coeff(row, col); m_argImpl.coeffRef(row, col) = nonconst_other.coeff(row, col); nonconst_other.coeffRef(row, col) = tmp; } template void copyCoeff(Index index, const OtherEvaluatorType& other) { OtherEvaluatorType& nonconst_other = const_cast(other); Scalar tmp = m_argImpl.coeff(index); m_argImpl.coeffRef(index) = nonconst_other.coeff(index); nonconst_other.coeffRef(index) = tmp; } template void copyPacket(Index row, Index col, const OtherEvaluatorType& other) { OtherEvaluatorType& nonconst_other = const_cast(other); Packet tmp = m_argImpl.template packet(row, col); m_argImpl.template writePacket (row, col, nonconst_other.template packet(row, col)); nonconst_other.template writePacket(row, col, tmp); } template void copyPacket(Index index, const OtherEvaluatorType& other) { OtherEvaluatorType& nonconst_other = const_cast(other); Packet tmp = m_argImpl.template packet(index); m_argImpl.template writePacket (index, nonconst_other.template packet(index)); nonconst_other.template writePacket(index, tmp); } protected: typename evaluator::type m_argImpl; }; // ---------- SelfCwiseBinaryOp ---------- template struct evaluator_impl > : evaluator_impl_base > { typedef SelfCwiseBinaryOp XprType; evaluator_impl(const XprType& selfCwiseBinaryOp) : m_argImpl(selfCwiseBinaryOp.expression()), m_functor(selfCwiseBinaryOp.functor()) { } typedef typename XprType::Index Index; typedef typename XprType::Scalar Scalar; typedef typename XprType::Packet Packet; // This function and the next one are needed by assign to correctly align loads/stores // TODO make Assign use .data() Scalar& coeffRef(Index row, Index col) { return m_argImpl.coeffRef(row, col); } inline Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } template void copyCoeff(Index row, Index col, const OtherEvaluatorType& other) { Scalar& tmp = m_argImpl.coeffRef(row, col); tmp = m_functor(tmp, other.coeff(row, col)); } template void copyCoeff(Index index, const OtherEvaluatorType& other) { Scalar& tmp = m_argImpl.coeffRef(index); tmp = m_functor(tmp, other.coeff(index)); } template void copyPacket(Index row, Index col, const OtherEvaluatorType& other) { const Packet res = m_functor.packetOp(m_argImpl.template packet(row, col), other.template packet(row, col)); m_argImpl.template writePacket(row, col, res); } template void copyPacket(Index index, const OtherEvaluatorType& other) { const Packet res = m_functor.packetOp(m_argImpl.template packet(index), other.template packet(index)); m_argImpl.template writePacket(index, res); } protected: typename evaluator::type m_argImpl; const BinaryOp m_functor; }; } // namespace internal } // end namespace Eigen #endif // EIGEN_COREEVALUATORS_H