diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index 2b251bc2c..b7dafd3ee 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -242,6 +242,21 @@ template::type& nestedExpression() const + { + return m_xpr; + } + + Index startRow() const + { + return m_startRow.value(); + } + + Index startCol() const + { + return m_startCol.value(); + } + protected: const typename XprType::Nested m_xpr; @@ -304,6 +319,11 @@ class Block init(); } + const typename internal::remove_all::type& nestedExpression() const + { + return m_xpr; + } + /** \sa MapBase::innerStride() */ inline Index innerStride() const { diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index 4dd466bc6..39ef6078c 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -39,6 +39,8 @@ struct evaluator typedef evaluator_impl type; }; +// TODO: Think about const-correctness + template struct evaluator { @@ -369,69 +371,166 @@ protected: }; // -------------------- Block -------------------- -// -// This evaluator is implemented as a dumb wrapper around Block expression class. -// TODO: Make this a real evaluator -template -struct evaluator_impl > +template +struct evaluator_impl > { - typedef Block BlockType; - evaluator_impl(const BlockType& block) : m_block(block) { } + 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 i, Index j) const + CoeffReturnType coeff(Index row, Index col) const { - return m_block.coeff(i,j); + return m_argImpl.coeff(m_startRow + row, m_startCol + col); } CoeffReturnType coeff(Index index) const { - return m_block.coeff(index); + return m_argImpl.coeff(m_startRow + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol + (RowsAtCompileTime == 1 ? index : 0)); } - Scalar& coeffRef(Index i, Index j) + Scalar& coeffRef(Index row, Index col) { - return m_block.const_cast_derived().coeffRef(i,j); + return m_argImpl.coeffRef(m_startRow + row, m_startCol + col); } Scalar& coeffRef(Index index) { - return m_block.const_cast_derived().coeffRef(index); + return m_argImpl.coeffRef(m_startRow + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol + (RowsAtCompileTime == 1 ? index : 0)); } template PacketReturnType packet(Index row, Index col) const { - return m_block.template packet(row, col); + return m_argImpl.template packet(m_startRow + row, m_startCol + col); } template PacketReturnType packet(Index index) const { - return m_block.template packet(index); + return m_argImpl.template packet(m_startRow + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol + (RowsAtCompileTime == 1 ? index : 0)); } template void writePacket(Index row, Index col, const PacketScalar& x) { - m_block.const_cast_derived().template writePacket(row, col, x); + return m_argImpl.template writePacket(m_startRow + row, m_startCol + col, x); } template void writePacket(Index index, const PacketScalar& x) { - m_block.const_cast_derived().template writePacket(index, x); + return m_argImpl.template writePacket(m_startRow + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol + (RowsAtCompileTime == 1 ? index : 0), + x); } protected: - const BlockType& m_block; + 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 > +{ + typedef Block BlockType; + typedef typename BlockType::PointerType PointerType; + 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; + + evaluator_impl(const BlockType& block) + : m_argImpl(block.nestedExpression()), + m_data(const_cast(block.data())), + m_rowStride(block.rowStride()), + m_colStride(block.colStride()) + { } + + enum { + RowsAtCompileTime = BlockType::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: + typename evaluator::type m_argImpl; + PointerType m_data; + int m_rowStride; + int m_colStride; };