Complete rewrite of partial reduction according to mailing list discussions.

This commit is contained in:
Gael Guennebaud 2008-07-19 11:36:32 +00:00
parent 8b4945a5a2
commit 7245c63067
4 changed files with 167 additions and 47 deletions

View File

@ -28,26 +28,29 @@
/** \array_module /** \array_module
* *
* \class PartialRedux * \class PartialReduxExpr
* *
* \brief Generic expression of a partially reduxed matrix * \brief Generic expression of a partially reduxed matrix
* *
* \param Direction indicates the direction of the redux (Vertical or Horizontal)
* \param BinaryOp type of the binary functor implementing the operator (must be associative)
* \param MatrixType the type of the matrix we are applying the redux operation * \param MatrixType the type of the matrix we are applying the redux operation
* \param MemberOp type of the member functor
* \param Direction indicates the direction of the redux (Vertical or Horizontal)
* *
* This class represents an expression of a partial redux operator of a matrix. * This class represents an expression of a partial redux operator of a matrix.
* It is the return type of MatrixBase::verticalRedux(), MatrixBase::horizontalRedux(), * It is the return type of PartialRedux functions,
* and most of the time this is the only way it is used. * and most of the time this is the only way it is used.
* *
* \sa class CwiseBinaryOp * \sa class PartialRedux
*/ */
template<int Direction, typename BinaryOp, typename MatrixType>
struct ei_traits<PartialRedux<Direction, BinaryOp, MatrixType> > template< typename MatrixType, typename MemberOp, int Direction>
class PartialReduxExpr;
template<typename MatrixType, typename MemberOp, int Direction>
struct ei_traits<PartialReduxExpr<MatrixType, MemberOp, Direction> >
{ {
typedef typename ei_result_of< typedef typename MemberOp::result_type Scalar;
BinaryOp(typename MatrixType::Scalar) typedef typename MatrixType::Scalar InputScalar;
>::type Scalar;
typedef typename ei_nested<MatrixType>::type MatrixTypeNested; typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested; typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
enum { enum {
@ -60,73 +63,194 @@ struct ei_traits<PartialRedux<Direction, BinaryOp, MatrixType> >
: (unsigned int)_MatrixTypeNested::Flags & ~LargeBit) & HereditaryBits, : (unsigned int)_MatrixTypeNested::Flags & ~LargeBit) & HereditaryBits,
TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime, TraversalSize = Direction==Vertical ? RowsAtCompileTime : ColsAtCompileTime,
CoeffReadCost = TraversalSize * _MatrixTypeNested::CoeffReadCost CoeffReadCost = TraversalSize * _MatrixTypeNested::CoeffReadCost
+ (TraversalSize - 1) * ei_functor_traits<BinaryOp>::Cost + MemberOp::template Cost<InputScalar,TraversalSize>::value
}; };
}; };
template<int Direction, typename BinaryOp, typename MatrixType> template< typename MatrixType, typename MemberOp, int Direction>
class PartialRedux : ei_no_assignment_operator, class PartialReduxExpr : ei_no_assignment_operator,
public MatrixBase<PartialRedux<Direction, BinaryOp, MatrixType> > public MatrixBase<PartialReduxExpr<MatrixType, MemberOp, Direction> >
{ {
public: public:
EIGEN_GENERIC_PUBLIC_INTERFACE(PartialRedux) EIGEN_GENERIC_PUBLIC_INTERFACE(PartialReduxExpr)
typedef typename ei_traits<PartialRedux>::MatrixTypeNested MatrixTypeNested; typedef typename ei_traits<PartialReduxExpr>::MatrixTypeNested MatrixTypeNested;
typedef typename ei_traits<PartialRedux>::_MatrixTypeNested _MatrixTypeNested; typedef typename ei_traits<PartialReduxExpr>::_MatrixTypeNested _MatrixTypeNested;
PartialRedux(const MatrixType& mat, const BinaryOp& func = BinaryOp()) PartialReduxExpr(const MatrixType& mat, const MemberOp& func = MemberOp())
: m_matrix(mat), m_functor(func) {} : m_matrix(mat), m_functor(func) {}
private:
int rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); } int rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); }
int cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); } int cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }
const Scalar coeff(int i, int j) const const Scalar coeff(int i, int j) const
{ {
if (Direction==Vertical) if (Direction==Vertical)
return m_matrix.col(j).redux(m_functor); return m_functor(m_matrix.col(j));
else else
return m_matrix.row(i).redux(m_functor); return m_functor(m_matrix.row(i));
} }
protected: protected:
const MatrixTypeNested m_matrix; const MatrixTypeNested m_matrix;
const BinaryOp m_functor; const MemberOp m_functor;
};
#define EIGEN_MEMBER_FUNCTOR(MEMBER,COST) \
template <typename ResultType> \
struct ei_member_##MEMBER EIGEN_EMPTY_STRUCT { \
typedef ResultType result_type; \
template<typename Scalar, int Size> struct Cost \
{ enum { value = COST }; }; \
template<typename Derived> \
inline ResultType operator()(const MatrixBase<Derived>& mat) const \
{ return mat.MEMBER(); } \
}
EIGEN_MEMBER_FUNCTOR(norm2, Size * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(norm, (Size+5) * NumTraits<Scalar>::MulCost + (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(sum, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(minCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
EIGEN_MEMBER_FUNCTOR(maxCoeff, (Size-1)*NumTraits<Scalar>::AddCost);
/** \internal */
template <typename BinaryOp, typename Scalar>
struct ei_member_redux {
typedef typename ei_result_of<
BinaryOp(Scalar)
>::type result_type;
template<typename _Scalar, int Size> struct Cost
{ enum { value = (Size-1) * ei_functor_traits<BinaryOp>::Cost }; };
ei_member_redux(const BinaryOp func) : m_functor(func) {}
template<typename Derived>
inline result_type operator()(const MatrixBase<Derived>& mat) const
{ return mat.redux(m_functor); }
const BinaryOp m_functor;
}; };
/** \array_module /** \array_module
*
* \returns a row vector expression of *this vertically reduxed by \a func
* *
* The template parameter \a BinaryOp is the type of the functor * \class PartialRedux
* of the custom redux operator. Note that func must be an associative operator.
* *
* \sa class PartialRedux, MatrixBase::horizontalRedux() * \brief Pseudo expression providing partial reduction operations
*
* \param ExpressionType the type of the object on which to do partial reductions
* \param Direction indicates the direction of the redux (Vertical or Horizontal)
*
* This class represents an expression with additional partial reduction features.
* It is the return type of MatrixBase::colwise() and MatrixBase::rowwise()
* and most of the time this is the only way it is used.
*
* \sa MatrixBase::colwise(), MatrixBase::rowwise()
*/
template<typename ExpressionType, int Direction> class PartialRedux
{
public:
typedef typename ei_traits<ExpressionType>::Scalar Scalar;
typedef typename ei_meta_if<ei_must_nest_by_value<ExpressionType>::ret,
ExpressionType, const ExpressionType&>::ret ExpressionTypeNested;
template<template<typename _Scalar> class Functor> struct ReturnType
{
typedef PartialReduxExpr<ExpressionType,
Functor<typename ei_traits<ExpressionType>::Scalar>,
Direction
> Type;
};
template<typename BinaryOp> struct ReduxReturnType
{
typedef PartialReduxExpr<ExpressionType,
ei_member_redux<BinaryOp,typename ei_traits<ExpressionType>::Scalar>,
Direction
> Type;
};
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */
inline const ExpressionType& _expression() const { return m_matrix; }
template<typename BinaryOp>
const typename ReduxReturnType<BinaryOp>::Type
redux(const BinaryOp& func = BinaryOp()) const;
/** \returns a row (or column) vector expression of the smallest coefficient
* of each column (or row) of the referenced expression.
* \sa MatrixBase::minCoeff() */
const typename ReturnType<ei_member_minCoeff>::Type minCoeff() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the largest coefficient
* of each column (or row) of the referenced expression.
* \sa MatrixBase::maxCoeff() */
const typename ReturnType<ei_member_maxCoeff>::Type maxCoeff() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the squared norm
* of each column (or row) of the referenced expression.
* \sa MatrixBase::norm2() */
const typename ReturnType<ei_member_norm2>::Type norm2() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the norm
* of each column (or row) of the referenced expression.
* \sa MatrixBase::norm() */
const typename ReturnType<ei_member_norm>::Type norm() const
{ return _expression(); }
/** \returns a row (or column) vector expression of the sum
* of each column (or row) of the referenced expression.
* \sa MatrixBase::sum() */
const typename ReturnType<ei_member_sum>::Type sum() const
{ return _expression(); }
protected:
ExpressionTypeNested m_matrix;
};
/** \array_module
*
* \returns a PartialRedux wrapper of *this providing additional partial reduction operations
*
* \sa class PartialRedux
*/ */
template<typename Derived> template<typename Derived>
template<typename BinaryOp> inline const PartialRedux<Derived,Vertical>
const PartialRedux<Vertical, BinaryOp, Derived> MatrixBase<Derived>::colwise() const
MatrixBase<Derived>::verticalRedux(const BinaryOp& func) const
{ {
return PartialRedux<Vertical, BinaryOp, Derived>(derived(), func); return derived();
}
/** \array_module
*
* \returns a PartialRedux wrapper of *this providing additional partial reduction operations
*
* \sa class PartialRedux
*/
template<typename Derived>
inline const PartialRedux<Derived,Horizontal>
MatrixBase<Derived>::rowwise() const
{
return derived();
} }
/** \array_module /** \array_module
* *
* \returns a row vector expression of *this horizontally reduxed by \a func * \returns a row or column vector expression of \c *this reduxed by \a func
* *
* The template parameter \a BinaryOp is the type of the functor * The template parameter \a BinaryOp is the type of the functor
* of the custom redux operator. Note that func must be an associative operator. * of the custom redux operator. Note that func must be an associative operator.
* *
* \sa class PartialRedux, MatrixBase::verticalRedux() * \sa class PartialRedux, MatrixBase::colwise(), MatrixBase::rowwise()
*/ */
template<typename Derived> template<typename ExpressionType, int Direction>
template<typename BinaryOp> template<typename BinaryOp>
const PartialRedux<Horizontal, BinaryOp, Derived> const typename PartialRedux<ExpressionType,Direction>::template ReduxReturnType<BinaryOp>::Type
MatrixBase<Derived>::horizontalRedux(const BinaryOp& func) const PartialRedux<ExpressionType,Direction>::redux(const BinaryOp& func) const
{ {
return PartialRedux<Horizontal, BinaryOp, Derived>(derived(), func); return typename ReduxReturnType<BinaryOp>::Type(_expression(), func);
} }
#endif // EIGEN_PARTIAL_REDUX_H #endif // EIGEN_PARTIAL_REDUX_H

View File

@ -501,13 +501,8 @@ template<typename Derived> class MatrixBase
bool all(void) const; bool all(void) const;
bool any(void) const; bool any(void) const;
template<typename BinaryOp> const PartialRedux<Derived,Horizontal> rowwise() const;
const PartialRedux<Vertical, BinaryOp, Derived> const PartialRedux<Derived,Vertical> colwise() const;
verticalRedux(const BinaryOp& func) const;
template<typename BinaryOp>
const PartialRedux<Horizontal, BinaryOp, Derived>
horizontalRedux(const BinaryOp& func) const;
static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> random(int rows, int cols); static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> random(int rows, int cols);
static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> random(int size); static const CwiseNullaryOp<ei_scalar_random_op<Scalar>,Derived> random(int size);

View File

@ -81,7 +81,7 @@ struct ei_redux_impl<BinaryOp, Derived, Start, Dynamic>
* The template parameter \a BinaryOp is the type of the functor \a func which must be * The template parameter \a BinaryOp is the type of the functor \a func which must be
* an assiociative operator. Both current STL and TR1 functor styles are handled. * an assiociative operator. Both current STL and TR1 functor styles are handled.
* *
* \sa MatrixBase::sum(), MatrixBase::minCoeff(), MatrixBase::maxCoeff(), MatrixBase::verticalRedux(), MatrixBase::horizontalRedux() * \sa MatrixBase::sum(), MatrixBase::minCoeff(), MatrixBase::maxCoeff(), MatrixBase::colwise(), MatrixBase::rowwise()
*/ */
template<typename Derived> template<typename Derived>
template<typename BinaryOp> template<typename BinaryOp>

View File

@ -53,10 +53,11 @@ template<typename Lhs, typename Rhs, int ProductMode> class Product;
template<typename CoeffsVectorType> class DiagonalMatrix; template<typename CoeffsVectorType> class DiagonalMatrix;
template<typename MatrixType> class DiagonalCoeffs; template<typename MatrixType> class DiagonalCoeffs;
template<typename MatrixType, int Alignment = Unaligned> class Map; template<typename MatrixType, int Alignment = Unaligned> class Map;
template<int Direction, typename UnaryOp, typename MatrixType> class PartialRedux;
template<typename MatrixType, unsigned int Mode> class Part; template<typename MatrixType, unsigned int Mode> class Part;
template<typename MatrixType, unsigned int Mode> class Extract; template<typename MatrixType, unsigned int Mode> class Extract;
template<typename ExpressionType> class Cwise; template<typename ExpressionType> class Cwise;
template<typename ExpressionType, int Direction> class PartialRedux;
template<typename MatrixType, typename BinaryOp, int Direction> class PartialReduxExpr;
template<typename Lhs, typename Rhs> struct ei_product_mode; template<typename Lhs, typename Rhs> struct ei_product_mode;
template<typename Lhs, typename Rhs, int ProductMode = ei_product_mode<Lhs,Rhs>::value> struct ProductReturnType; template<typename Lhs, typename Rhs, int ProductMode = ei_product_mode<Lhs,Rhs>::value> struct ProductReturnType;