// 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 internal { template struct evaluator_impl {}; template struct evaluator { typedef evaluator_impl type; }; // TODO: Think about const-correctness template struct evaluator { typedef evaluator_impl type; }; // -------------------- Transpose -------------------- template struct evaluator_impl > { typedef Transpose TransposeType; evaluator_impl(const TransposeType& t) : m_argImpl(t.nestedExpression()) {} typedef typename TransposeType::Index Index; typename TransposeType::CoeffReturnType coeff(Index i, Index j) const { return m_argImpl.coeff(j, i); } typename TransposeType::CoeffReturnType coeff(Index index) const { return m_argImpl.coeff(index); } typename TransposeType::Scalar& coeffRef(Index i, Index j) { return m_argImpl.coeffRef(j, i); } typename TransposeType::Scalar& coeffRef(Index index) { return m_argImpl.coeffRef(index); } // TODO: Difference between PacketScalar and PacketReturnType? template const typename ExpressionType::PacketScalar packet(Index row, Index col) const { return m_argImpl.template packet(col, row); } template const typename ExpressionType::PacketScalar packet(Index index) const { return m_argImpl.template packet(index); } template void writePacket(Index row, Index col, const typename ExpressionType::PacketScalar& x) { m_argImpl.template writePacket(col, row, x); } template void writePacket(Index index, const typename ExpressionType::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 > { 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 MatrixType; evaluator_impl(const MatrixType& m) : evaluator_impl >(m) { } }; template struct evaluator_impl > : evaluator_impl > > { typedef Array ArrayType; evaluator_impl(const ArrayType& m) : evaluator_impl >(m) { } }; // -------------------- CwiseNullaryOp -------------------- template struct evaluator_impl > { typedef CwiseNullaryOp NullaryOpType; evaluator_impl(const NullaryOpType& n) : m_functor(n.functor()) { } typedef typename NullaryOpType::Index Index; typedef typename NullaryOpType::CoeffReturnType CoeffReturnType; typedef typename NullaryOpType::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 index) const { return m_functor.packetOp(index); } protected: const NullaryOp m_functor; }; // -------------------- CwiseUnaryOp -------------------- template struct evaluator_impl > { typedef CwiseUnaryOp UnaryOpType; evaluator_impl(const UnaryOpType& op) : m_functor(op.functor()), m_argImpl(op.nestedExpression()) { } typedef typename UnaryOpType::Index Index; typedef typename UnaryOpType::CoeffReturnType CoeffReturnType; typedef typename UnaryOpType::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 BinaryOpType; evaluator_impl(const BinaryOpType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) { } typedef typename BinaryOpType::Index Index; typedef typename BinaryOpType::CoeffReturnType CoeffReturnType; typedef typename BinaryOpType::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 > { typedef CwiseUnaryView CwiseUnaryViewType; evaluator_impl(const CwiseUnaryViewType& op) : m_unaryOp(op.functor()), m_argImpl(op.nestedExpression()) { } typedef typename CwiseUnaryViewType::Index Index; typedef typename CwiseUnaryViewType::Scalar Scalar; typedef typename CwiseUnaryViewType::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; }; // -------------------- Product -------------------- template struct evaluator_impl > : public evaluator::PlainObject>::type { typedef Product XprType; typedef typename XprType::PlainObject PlainObject; typedef typename evaluator::type evaluator_base; // enum { // EvaluateLhs = ; // EvaluateRhs = ; // }; evaluator_impl(const XprType& product) : evaluator_base(m_result) { // here we process the left and right hand sides with a specialized evaluator // perhaps this step should be done by the TreeOptimizer to get a canonical tree and reduce evaluator instanciations // typename product_operand_evaluator::type m_lhsImpl(product.lhs()); // typename product_operand_evaluator::type m_rhsImpl(product.rhs()); // TODO do not rely on previous product mechanism !! m_result.resize(product.rows(), product.cols()); m_result.noalias() = product.lhs() * product.rhs(); } protected: PlainObject m_result; }; // -------------------- Map -------------------- template struct evaluator_impl > { typedef MapBase MapType; typedef typename MapType::PointerType PointerType; typedef typename MapType::Index Index; typedef typename MapType::Scalar Scalar; typedef typename MapType::CoeffReturnType CoeffReturnType; typedef typename MapType::PacketScalar PacketScalar; typedef typename MapType::PacketReturnType PacketReturnType; evaluator_impl(const MapType& map) : m_data(const_cast(map.data())), m_rowStride(map.rowStride()), m_colStride(map.colStride()) { } enum { RowsAtCompileTime = MapType::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 MapType; evaluator_impl(const MapType& map) : evaluator_impl >(map) { } }; // -------------------- Block -------------------- template struct evaluator_impl > { typedef Block BlockType; evaluator_impl(const BlockType& block) : m_argImpl(block.nestedExpression()), m_startRow(block.startRow()), m_startCol(block.startCol()) { } typedef typename BlockType::Index Index; typedef typename BlockType::Scalar Scalar; typedef typename BlockType::CoeffReturnType CoeffReturnType; typedef typename BlockType::PacketScalar PacketScalar; typedef typename BlockType::PacketReturnType PacketReturnType; enum { RowsAtCompileTime = BlockType::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 BlockType; evaluator_impl(const BlockType& block) : evaluator_impl >(block) { } }; // -------------------- Select -------------------- template struct evaluator_impl > { typedef Select SelectType; evaluator_impl(const SelectType& select) : m_conditionImpl(select.conditionMatrix()), m_thenImpl(select.thenMatrix()), m_elseImpl(select.elseMatrix()) { } typedef typename SelectType::Index Index; typedef typename SelectType::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 ReplicateType; evaluator_impl(const ReplicateType& replicate) : m_argImpl(replicate.nestedExpression()), m_rows(replicate.nestedExpression().rows()), m_cols(replicate.nestedExpression().cols()) { } typedef typename ReplicateType::Index Index; typedef typename ReplicateType::CoeffReturnType CoeffReturnType; typedef typename ReplicateType::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; Index m_cols; }; } // namespace internal #endif // EIGEN_COREEVALUATORS_H