// 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; }; 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 -------------------- template struct evaluator_impl > { typedef Matrix MatrixType; evaluator_impl(const MatrixType& m) : m_matrix(m) {} typedef typename MatrixType::Index Index; typename MatrixType::CoeffReturnType coeff(Index i, Index j) const { return m_matrix.coeff(i, j); } typename MatrixType::CoeffReturnType coeff(Index index) const { return m_matrix.coeff(index); } typename MatrixType::Scalar& coeffRef(Index i, Index j) { return m_matrix.const_cast_derived().coeffRef(i, j); } typename MatrixType::Scalar& coeffRef(Index index) { return m_matrix.const_cast_derived().coeffRef(index); } template typename MatrixType::PacketReturnType packet(Index row, Index col) const { return m_matrix.template packet(row, col); } template typename MatrixType::PacketReturnType packet(Index index) const { // eigen_internal_assert(index >= 0 && index < size()); return m_matrix.template packet(index); } template void writePacket(Index row, Index col, const typename MatrixType::PacketScalar& x) { m_matrix.const_cast_derived().template writePacket(row, col, x); } template void writePacket(Index index, const typename MatrixType::PacketScalar& x) { // eigen_internal_assert(index >= 0 && index < size()); m_matrix.const_cast_derived().template writePacket(index, x); } protected: const MatrixType &m_matrix; }; // -------------------- Array -------------------- // TODO: should be sharing code with Matrix case template struct evaluator_impl > { typedef Array ArrayType; evaluator_impl(const ArrayType& a) : m_array(a) {} typedef typename ArrayType::Index Index; typename ArrayType::CoeffReturnType coeff(Index i, Index j) const { return m_array.coeff(i, j); } typename ArrayType::CoeffReturnType coeff(Index index) const { return m_array.coeff(index); } typename ArrayType::Scalar& coeffRef(Index i, Index j) { return m_array.const_cast_derived().coeffRef(i, j); } typename ArrayType::Scalar& coeffRef(Index index) { return m_array.const_cast_derived().coeffRef(index); } template typename ArrayType::PacketReturnType packet(Index row, Index col) const { return m_array.template packet(row, col); } template typename ArrayType::PacketReturnType packet(Index index) const { // eigen_internal_assert(index >= 0 && index < size()); return m_array.template packet(index); } template void writePacket(Index row, Index col, const typename ArrayType::PacketScalar& x) { m_array.const_cast_derived().template writePacket(row, col, x); } template void writePacket(Index index, const typename ArrayType::PacketScalar& x) { // eigen_internal_assert(index >= 0 && index < size()); m_array.const_cast_derived().template writePacket(index, x); } protected: const ArrayType &m_array; }; // -------------------- CwiseNullaryOp -------------------- template struct evaluator_impl > { typedef CwiseNullaryOp NullaryOpType; evaluator_impl(const NullaryOpType& n) : m_nullaryOp(n) {} typedef typename NullaryOpType::Index Index; typename NullaryOpType::CoeffReturnType coeff(Index i, Index j) const { return m_nullaryOp.coeff(i, j); } typename NullaryOpType::CoeffReturnType coeff(Index index) const { return m_nullaryOp.coeff(index); } template typename NullaryOpType::PacketScalar packet(Index index) const { return m_nullaryOp.template packet(index); } protected: const NullaryOpType& m_nullaryOp; }; // -------------------- CwiseUnaryOp -------------------- template struct evaluator_impl > { typedef CwiseUnaryOp UnaryOpType; evaluator_impl(const UnaryOpType& op) : m_unaryOp(op), m_argImpl(op.nestedExpression()) {} typedef typename UnaryOpType::Index Index; typename UnaryOpType::CoeffReturnType coeff(Index i, Index j) const { return m_unaryOp.functor()(m_argImpl.coeff(i, j)); } typename UnaryOpType::CoeffReturnType coeff(Index index) const { return m_unaryOp.functor()(m_argImpl.coeff(index)); } template typename UnaryOpType::PacketScalar packet(Index index) const { return m_unaryOp.functor().packetOp(m_argImpl.template packet(index)); } template typename UnaryOpType::PacketScalar packet(Index row, Index col) const { return m_unaryOp.functor().packetOp(m_argImpl.template packet(row, col)); } protected: const UnaryOpType& m_unaryOp; typename evaluator::type m_argImpl; }; // -------------------- CwiseBinaryOp -------------------- template struct evaluator_impl > { typedef CwiseBinaryOp BinaryOpType; evaluator_impl(const BinaryOpType& xpr) : m_binaryOp(xpr), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {} typedef typename BinaryOpType::Index Index; typename BinaryOpType::CoeffReturnType coeff(Index i, Index j) const { return m_binaryOp.functor()(m_lhsImpl.coeff(i, j), m_rhsImpl.coeff(i, j)); } typename BinaryOpType::CoeffReturnType coeff(Index index) const { return m_binaryOp.functor()(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index)); } template typename BinaryOpType::PacketScalar packet(Index index) const { return m_binaryOp.functor().packetOp(m_lhsImpl.template packet(index), m_rhsImpl.template packet(index)); } template typename BinaryOpType::PacketScalar packet(Index row, Index col) const { return m_binaryOp.functor().packetOp(m_lhsImpl.template packet(row, col), m_rhsImpl.template packet(row, col)); } protected: const BinaryOpType& m_binaryOp; typename evaluator::type m_lhsImpl; typename evaluator::type m_rhsImpl; }; // -------------------- 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; }; } // namespace internal #endif // EIGEN_COREEVALUATORS_H