Generalize Block<> to support various implementation wrt StorageKind (just like other expression)

This commit is contained in:
Gael Guennebaud 2012-11-16 09:00:27 +01:00
parent 493319ae5f
commit 3dc8f8536a
3 changed files with 117 additions and 59 deletions

View File

@ -21,7 +21,6 @@ namespace Eigen {
* \param XprType the type of the expression in which we are taking a block * \param XprType the type of the expression in which we are taking a block
* \param BlockRows the number of rows of the block we are taking at compile time (optional) * \param BlockRows the number of rows of the block we are taking at compile time (optional)
* \param BlockCols the number of columns of the block we are taking at compile time (optional) * \param BlockCols the number of columns of the block we are taking at compile time (optional)
* \param _DirectAccessStatus \internal used for partial specialization
* *
* This class represents an expression of either a fixed-size or dynamic-size block. It is the return * This class represents an expression of either a fixed-size or dynamic-size block. It is the return
* type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and
@ -47,8 +46,8 @@ namespace Eigen {
*/ */
namespace internal { namespace internal {
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType> struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprType>
{ {
typedef typename traits<XprType>::Scalar Scalar; typedef typename traits<XprType>::Scalar Scalar;
typedef typename traits<XprType>::StorageKind StorageKind; typedef typename traits<XprType>::StorageKind StorageKind;
@ -92,30 +91,27 @@ struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess>
Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
}; };
}; };
}
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
: public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class BlockImpl_dense;
} // end namespace internal
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind> class BlockImpl;
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class Block
: public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind>
{ {
typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl;
public: public:
//typedef typename Impl::Base Base;
typedef typename internal::dense_xpr_base<Block>::type Base; typedef Impl Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Block) EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
class InnerIterator;
/** Column or Row constructor /** Column or Row constructor
*/ */
inline Block(XprType& xpr, Index i) inline Block(XprType& xpr, Index i) : Impl(xpr,i)
: m_xpr(xpr),
// It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
// and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
// all other cases are invalid.
// The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
m_blockCols(BlockCols==1 ? 1 : xpr.cols())
{ {
eigen_assert( (i>=0) && ( eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
@ -125,8 +121,7 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
/** Fixed-size constructor /** Fixed-size constructor
*/ */
inline Block(XprType& xpr, Index a_startRow, Index a_startCol) inline Block(XprType& xpr, Index a_startRow, Index a_startCol)
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol), : Impl(xpr, a_startRow, a_startCol)
m_blockRows(BlockRows), m_blockCols(BlockCols)
{ {
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
eigen_assert(a_startRow >= 0 && BlockRows >= 1 && a_startRow + BlockRows <= xpr.rows() eigen_assert(a_startRow >= 0 && BlockRows >= 1 && a_startRow + BlockRows <= xpr.rows()
@ -138,16 +133,75 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
inline Block(XprType& xpr, inline Block(XprType& xpr,
Index a_startRow, Index a_startCol, Index a_startRow, Index a_startCol,
Index blockRows, Index blockCols) Index blockRows, Index blockCols)
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol), : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols)
m_blockRows(blockRows), m_blockCols(blockCols)
{ {
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
eigen_assert(a_startRow >= 0 && blockRows >= 0 && a_startRow + blockRows <= xpr.rows() eigen_assert(a_startRow >= 0 && blockRows >= 0 && a_startRow + blockRows <= xpr.rows()
&& a_startCol >= 0 && blockCols >= 0 && a_startCol + blockCols <= xpr.cols()); && a_startCol >= 0 && blockCols >= 0 && a_startCol + blockCols <= xpr.cols());
} }
};
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) // The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense
// that must be specialized for direct and non-direct access...
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
: public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel>
{
typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl;
typedef typename XprType::Index Index;
public:
typedef Impl Base;
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
inline BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {}
inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol) : Impl(xpr, a_startRow, a_startCol) {}
inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol, Index blockRows, Index blockCols)
: Impl(xpr, a_startRow, a_startCol, blockRows, blockCols) {}
};
namespace internal {
/** \internal Internal implementation of dense Blocks in the general case. */
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class BlockImpl_dense
: public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel> >::type
{
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
public:
typedef typename internal::dense_xpr_base<BlockType>::type Base;
EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
class InnerIterator;
/** Column or Row constructor
*/
inline BlockImpl_dense(XprType& xpr, Index i)
: m_xpr(xpr),
// It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
// and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
// all other cases are invalid.
// The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
m_blockCols(BlockCols==1 ? 1 : xpr.cols())
{}
/** Fixed-size constructor
*/
inline BlockImpl_dense(XprType& xpr, Index a_startRow, Index a_startCol)
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol)
{}
/** Dynamic-size constructor
*/
inline BlockImpl_dense(XprType& xpr,
Index a_startRow, Index a_startCol,
Index blockRows, Index blockCols)
: m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
m_blockRows(blockRows), m_blockCols(blockCols)
{ }
inline Index rows() const { return m_blockRows.value(); } inline Index rows() const { return m_blockRows.value(); }
inline Index cols() const { return m_blockCols.value(); } inline Index cols() const { return m_blockCols.value(); }
@ -253,21 +307,21 @@ template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool H
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
}; };
/** \internal */ /** \internal Internal implementation of dense Blocks in the direct access case.*/
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class Block<XprType,BlockRows,BlockCols, InnerPanel,true> class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
: public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> > : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >
{ {
typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
public: public:
typedef MapBase<Block> Base; typedef MapBase<BlockType> Base;
EIGEN_DENSE_PUBLIC_INTERFACE(Block) EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
/** Column or Row constructor /** Column or Row constructor
*/ */
inline Block(XprType& xpr, Index i) inline BlockImpl_dense(XprType& xpr, Index i)
: Base(internal::const_cast_ptr(&xpr.coeffRef( : Base(internal::const_cast_ptr(&xpr.coeffRef(
(BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0, (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
(BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)), (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
@ -275,34 +329,25 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
BlockCols==1 ? 1 : xpr.cols()), BlockCols==1 ? 1 : xpr.cols()),
m_xpr(xpr) m_xpr(xpr)
{ {
eigen_assert( (i>=0) && (
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
init(); init();
} }
/** Fixed-size constructor /** Fixed-size constructor
*/ */
inline Block(XprType& xpr, Index startRow, Index startCol) inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr) : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
{ {
eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
init(); init();
} }
/** Dynamic-size constructor /** Dynamic-size constructor
*/ */
inline Block(XprType& xpr, inline BlockImpl_dense(XprType& xpr,
Index startRow, Index startCol, Index startRow, Index startCol,
Index blockRows, Index blockCols) Index blockRows, Index blockCols)
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols), : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
m_xpr(xpr) m_xpr(xpr)
{ {
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
&& startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
init(); init();
} }
@ -314,7 +359,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
/** \sa MapBase::innerStride() */ /** \sa MapBase::innerStride() */
inline Index innerStride() const inline Index innerStride() const
{ {
return internal::traits<Block>::HasSameStorageOrderAsXprType return internal::traits<BlockType>::HasSameStorageOrderAsXprType
? m_xpr.innerStride() ? m_xpr.innerStride()
: m_xpr.outerStride(); : m_xpr.outerStride();
} }
@ -333,7 +378,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
#ifndef EIGEN_PARSED_BY_DOXYGEN #ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal used by allowAligned() */ /** \internal used by allowAligned() */
inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols) inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
: Base(data, blockRows, blockCols), m_xpr(xpr) : Base(data, blockRows, blockCols), m_xpr(xpr)
{ {
init(); init();
@ -343,7 +388,7 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
protected: protected:
void init() void init()
{ {
m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType
? m_xpr.outerStride() ? m_xpr.outerStride()
: m_xpr.innerStride(); : m_xpr.innerStride();
} }
@ -352,6 +397,8 @@ class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
Index m_outerStride; Index m_outerStride;
}; };
} // end namespace internal
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_BLOCK_H #endif // EIGEN_BLOCK_H

View File

@ -708,13 +708,25 @@ struct evaluator_impl<Map<PlainObjectType, MapOptions, StrideType> >
// -------------------- Block -------------------- // -------------------- Block --------------------
template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel,
struct evaluator_impl<Block<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ false> > bool HasDirectAccess = internal::has_direct_access<ArgType>::ret> struct block_evaluator;
: evaluator_impl_base<Block<ArgType, BlockRows, BlockCols, InnerPanel, false> >
{
typedef Block<ArgType, BlockRows, BlockCols, InnerPanel, false> XprType;
evaluator_impl(const XprType& block) 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_argImpl(block.nestedExpression()),
m_startRow(block.startRow()), m_startRow(block.startRow()),
m_startCol(block.startCol()) m_startCol(block.startCol())
@ -789,12 +801,12 @@ protected:
// all action is via the data() as returned by the Block expression. // all action is via the data() as returned by the Block expression.
template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
struct evaluator_impl<Block<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true> > struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true>
: evaluator_impl<MapBase<Block<ArgType, BlockRows, BlockCols, InnerPanel, true> > > : evaluator_impl<MapBase<Block<ArgType, BlockRows, BlockCols, InnerPanel> > >
{ {
typedef Block<ArgType, BlockRows, BlockCols, InnerPanel, true> XprType; typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
evaluator_impl(const XprType& block) block_evaluator(const XprType& block)
: evaluator_impl<MapBase<XprType> >(block) : evaluator_impl<MapBase<XprType> >(block)
{ } { }
}; };

View File

@ -78,8 +78,7 @@ template<typename ExpressionType> class NestByValue;
template<typename ExpressionType> class ForceAlignedAccess; template<typename ExpressionType> class ForceAlignedAccess;
template<typename ExpressionType> class SwapWrapper; template<typename ExpressionType> class SwapWrapper;
template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false, template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false> class Block;
bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class Block;
template<typename MatrixType, int Size=Dynamic> class VectorBlock; template<typename MatrixType, int Size=Dynamic> class VectorBlock;
template<typename MatrixType> class Transpose; template<typename MatrixType> class Transpose;