* Added a generic *redux* mini framework allowing custom redux operations

as well as partial redux (vertical or horizontal redux).
   Includes shortcuts for: sum, minCoeff and maxCoeff.
   There is no shortcut for the partial redux.

 * Added a generic *visitor* mini framework. A visitor is a custom object
   sequentially applied on each coefficient with knowledge of its value and
   coordinates.
   It is currentlly used to implement minCoeff(int*,int*) and maxCoeff(int*,int*).
   findBiggestCoeff is now a shortcut for "this->cwiseAbs().maxCoeff(i,j)"

 * Added coeff-wise min and max.
 * fixed an issue with ei_pow(int,int) and gcc < 4.3 or ICC
This commit is contained in:
Gael Guennebaud 2008-03-16 14:36:25 +00:00
parent 29184ad27d
commit 612350e3f8
10 changed files with 554 additions and 146 deletions

View File

@ -31,12 +31,14 @@ namespace Eigen {
#include "src/Core/DiagonalMatrix.h"
#include "src/Core/DiagonalCoeffs.h"
#include "src/Core/Identity.h"
#include "src/Core/SumOfCoeffs.h"
#include "src/Core/Redux.h"
#include "src/Core/Visitor.h"
#include "src/Core/Fuzzy.h"
#include "src/Core/Map.h"
#include "src/Core/IO.h"
#include "src/Core/Swap.h"
#include "src/Core/CommaInitializer.h"
#include "src/Core/AssociativeFunctors.h"
#include "src/Core/EvalOMP.h"
} // namespace Eigen

View File

@ -0,0 +1,64 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// 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 <http://www.gnu.org/licenses/>.
#ifndef EIGEN_ASSOCIATIVE_FUNCTORS_H
#define EIGEN_ASSOCIATIVE_FUNCTORS_H
/** \internal
* \brief Template functor to compute the sum of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator+, class PartialRedux, MatrixBase::sum()
*/
struct ei_scalar_sum_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
};
/** \internal
* \brief Template functor to compute the product of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseProduct(), class PartialRedux, MatrixBase::redux()
*/
struct ei_scalar_product_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return a * b; }
};
/** \internal
* \brief Template functor to compute the min of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class PartialRedux, MatrixBase::minCoeff()
*/
struct ei_scalar_min_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return ei_min(a, b); }
};
/** \internal
* \brief Template functor to compute the max of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class PartialRedux, MatrixBase::maxCoeff()
*/
struct ei_scalar_max_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return ei_max(a, b); }
};
#endif // EIGEN_ASSOCIATIVE_FUNCTORS_H

View File

@ -93,15 +93,6 @@ class CwiseBinaryOp : ei_no_assignment_operator,
const BinaryOp m_functor;
};
/** \internal
* \brief Template functor to compute the sum of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::operator+
*/
struct ei_scalar_sum_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
};
/** \internal
* \brief Template functor to compute the difference of two scalars
*
@ -111,15 +102,6 @@ struct ei_scalar_difference_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
};
/** \internal
* \brief Template functor to compute the product of two scalars
*
* \sa class CwiseBinaryOp, MatrixBase::cwiseProduct()
*/
struct ei_scalar_product_op EIGEN_EMPTY_STRUCT {
template<typename Scalar> Scalar operator() (const Scalar& a, const Scalar& b) const { return a * b; }
};
/** \internal
* \brief Template functor to compute the quotient of two scalars
*
@ -203,6 +185,30 @@ MatrixBase<Derived>::cwiseQuotient(const MatrixBase<OtherDerived> &other) const
return CwiseBinaryOp<ei_scalar_quotient_op, Derived, OtherDerived>(derived(), other.derived());
}
/** \returns an expression of the coefficient-wise min of *this and \a other
*
* \sa class CwiseBinaryOp
*/
template<typename Derived>
template<typename OtherDerived>
const CwiseBinaryOp<ei_scalar_min_op, Derived, OtherDerived>
MatrixBase<Derived>::cwiseMin(const MatrixBase<OtherDerived> &other) const
{
return CwiseBinaryOp<ei_scalar_min_op, Derived, OtherDerived>(derived(), other.derived());
}
/** \returns an expression of the coefficient-wise max of *this and \a other
*
* \sa class CwiseBinaryOp
*/
template<typename Derived>
template<typename OtherDerived>
const CwiseBinaryOp<ei_scalar_max_op, Derived, OtherDerived>
MatrixBase<Derived>::cwiseMax(const MatrixBase<OtherDerived> &other) const
{
return CwiseBinaryOp<ei_scalar_max_op, Derived, OtherDerived>(derived(), other.derived());
}
/** \returns an expression of a custom coefficient-wise operator \a func of *this and \a other
*
* The template parameter \a CustomBinaryOp is the type of the functor

View File

@ -45,6 +45,7 @@ template<typename MatrixType> class Identity;
template<typename MatrixType> class Map;
template<typename Derived> class Eval;
template<typename Derived> class EvalOMP;
template<int Direction, typename UnaryOp, typename MatrixType> class PartialRedux;
struct ei_scalar_sum_op;
struct ei_scalar_difference_op;
@ -62,6 +63,8 @@ struct ei_scalar_sin_op;
template<typename Scalar> struct ei_scalar_pow_op;
template<typename NewType> struct ei_scalar_cast_op;
template<typename Scalar> struct ei_scalar_multiple_op;
struct ei_scalar_min_op;
struct ei_scalar_max_op;
template<typename T> struct ei_xpr_copy
{

View File

@ -5,12 +5,12 @@
//
// 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
// 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
// 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
@ -18,7 +18,7 @@
// 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
// 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 <http://www.gnu.org/licenses/>.
@ -40,7 +40,11 @@ inline int ei_exp(int) { assert(false); return 0; }
inline int ei_log(int) { assert(false); return 0; }
inline int ei_sin(int) { assert(false); return 0; }
inline int ei_cos(int) { assert(false); return 0; }
#if (defined __ICC) || (defined __GNUC__ && (__GNUC__<4 || __GNUC_MINOR__<3))
inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
#else
inline int ei_pow(int x, int y) { return std::pow(x, y); }
#endif
template<> inline int ei_random(int a, int b)
{

View File

@ -81,7 +81,7 @@ template<typename Derived> class MatrixBase
/**< This is equal to the number of coefficients, i.e. the number of
* rows times the number of columns, or to \a Dynamic if this is not
* known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */
MaxRowsAtCompileTime = ei_traits<Derived>::MaxRowsAtCompileTime,
/**< This value is equal to the maximum possible number of rows that this expression
* might have. If this expression might have an arbitrarily high number of rows,
@ -245,13 +245,6 @@ template<typename Derived> class MatrixBase
Derived& operator*=(const MatrixBase<OtherDerived>& other);
//@}
/** \name Sums of coefficients
*/
//@{
Scalar sum() const;
Scalar trace() const;
//@}
/** \name Dot product and related notions
* including vector norm, adjoint, transpose ...
*/
@ -350,20 +343,7 @@ template<typename Derived> class MatrixBase
* which has the biggest absolute value.
*/
void findBiggestCoeff(int *row, int *col) const
{
RealScalar biggest = 0;
for(int j = 0; j < cols(); j++)
for(int i = 0; i < rows(); i++)
{
RealScalar x = ei_abs(coeff(i,j));
if(x > biggest)
{
biggest = x;
*row = i;
*col = j;
}
}
}
{ (*this).cwiseAbs().maxCoeff(row, col); }
//@}
/// \name Special functions
@ -396,6 +376,14 @@ template<typename Derived> class MatrixBase
const CwiseBinaryOp<ei_scalar_quotient_op, Derived, OtherDerived>
cwiseQuotient(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
const CwiseBinaryOp<ei_scalar_min_op, Derived, OtherDerived>
cwiseMin(const MatrixBase<OtherDerived> &other) const;
template<typename OtherDerived>
const CwiseBinaryOp<ei_scalar_max_op, Derived, OtherDerived>
cwiseMax(const MatrixBase<OtherDerived> &other) const;
const CwiseUnaryOp<ei_scalar_abs_op, Derived> cwiseAbs() const;
const CwiseUnaryOp<ei_scalar_abs2_op, Derived> cwiseAbs2() const;
const CwiseUnaryOp<ei_scalar_sqrt_op, Derived> cwiseSqrt() const;
@ -414,6 +402,33 @@ template<typename Derived> class MatrixBase
cwise(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func = CustomBinaryOp()) const;
//@}
/// \name Redux and visitor
//@{
Scalar sum() const;
Scalar trace() const;
typename ei_traits<Derived>::Scalar minCoeff() const;
typename ei_traits<Derived>::Scalar maxCoeff() const;
typename ei_traits<Derived>::Scalar minCoeff(int* row, int* col = 0) const;
typename ei_traits<Derived>::Scalar maxCoeff(int* row, int* col = 0) const;
template<typename BinaryOp>
const PartialRedux<Vertical, BinaryOp, Derived>
verticalRedux(const BinaryOp& func) const;
template<typename BinaryOp>
const PartialRedux<Horizontal, BinaryOp, Derived>
horizontalRedux(const BinaryOp& func) const;
template<typename BinaryOp>
typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
redux(const BinaryOp& func) const;
template<typename Visitor>
void visit(Visitor& func) const;
//@}
/// \name Casting to the derived type
//@{
const Derived& derived() const { return *static_cast<const Derived*>(this); }

232
Eigen/src/Core/Redux.h Normal file
View File

@ -0,0 +1,232 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
//
// 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 <http://www.gnu.org/licenses/>.
#ifndef EIGEN_REDUX_H
#define EIGEN_REDUX_H
template<typename BinaryOp, typename Derived, int Start, int Length>
struct ei_redux_unroller
{
enum {
HalfLength = Length/2
};
typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
static Scalar run(const Derived &mat, const BinaryOp& func)
{
return func(
ei_redux_unroller<BinaryOp, Derived, Start, HalfLength>::run(mat, func),
ei_redux_unroller<BinaryOp, Derived, Start+HalfLength, Length - HalfLength>::run(mat, func));
}
};
template<typename BinaryOp, typename Derived, int Start>
struct ei_redux_unroller<BinaryOp, Derived, Start, 1>
{
enum {
col = Start / Derived::RowsAtCompileTime,
row = Start % Derived::RowsAtCompileTime
};
typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
static Scalar run(const Derived &mat, const BinaryOp &func)
{
return mat.coeff(row, col);
}
};
template<typename BinaryOp, typename Derived, int Start>
struct ei_redux_unroller<BinaryOp, Derived, Start, Dynamic>
{
typedef typename ei_result_of<BinaryOp(typename Derived::Scalar)>::type Scalar;
static Scalar run(const Derived&, const BinaryOp&) { return Scalar(); }
};
/** \class PartialRedux
*
* \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
*
* This class represents an expression of a partial redux operator of a matrix.
* It is the return type of MatrixBase::verticalRedux(), MatrixBase::horizontalRedux(),
* and most of the time this is the only way it is used.
*
* \sa class CwiseBinaryOp
*/
template<int Direction, typename BinaryOp, typename MatrixType>
struct ei_traits<PartialRedux<Direction, BinaryOp, MatrixType> >
{
typedef typename ei_result_of<
BinaryOp(typename MatrixType::Scalar)
>::type Scalar;
enum {
RowsAtCompileTime = Direction==Vertical ? 1 : MatrixType::RowsAtCompileTime,
ColsAtCompileTime = Direction==Horizontal ? 1 : MatrixType::ColsAtCompileTime,
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
};
};
template<int Direction, typename BinaryOp, typename MatrixType>
class PartialRedux : ei_no_assignment_operator,
public MatrixBase<PartialRedux<Direction, BinaryOp, MatrixType> >
{
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(PartialRedux)
PartialRedux(const MatrixType& mat, const BinaryOp& func = BinaryOp())
: m_matrix(mat), m_functor(func) {}
private:
int _rows() const { return (Direction==Vertical ? 1 : m_matrix.rows()); }
int _cols() const { return (Direction==Horizontal ? 1 : m_matrix.cols()); }
Scalar _coeff(int i, int j) const
{
if (Direction==Vertical)
return this->col(j).redux(m_functor);
else
return this->row(i).redux(m_functor);
}
protected:
const typename MatrixType::XprCopy m_matrix;
const BinaryOp m_functor;
};
/** \returns a row vector expression of *this vertically reduxed by \a func
*
* The template parameter \a BinaryOp is the type of the functor
* of the custom redux operator. Note that func must be an associative operator.
*
* \sa class PartialRedux, MatrixBase::horizontalRedux()
*/
template<typename Derived>
template<typename BinaryOp>
const PartialRedux<Vertical, BinaryOp, Derived>
MatrixBase<Derived>::verticalRedux(const BinaryOp& func) const
{
return PartialRedux<Vertical, BinaryOp, Derived>(derived(), func);
}
/** \returns a row vector expression of *this horizontally reduxed by \a func
*
* The template parameter \a BinaryOp is the type of the functor
* of the custom redux operator. Note that func must be an associative operator.
*
* \sa class PartialRedux, MatrixBase::verticalRedux()
*/
template<typename Derived>
template<typename BinaryOp>
const PartialRedux<Horizontal, BinaryOp, Derived>
MatrixBase<Derived>::horizontalRedux(const BinaryOp& func) const
{
return PartialRedux<Horizontal, BinaryOp, Derived>(derived(), func);
}
/** \returns the result of a full redux operation on the whole matrix or vector using \a func
*
* 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.
*
* \sa MatrixBase::sum(), MatrixBase::minCoeff(), MatrixBase::maxCoeff(), MatrixBase::verticalRedux(), MatrixBase::horizontalRedux()
*/
template<typename Derived>
template<typename BinaryOp>
typename ei_result_of<BinaryOp(typename ei_traits<Derived>::Scalar)>::type
MatrixBase<Derived>::redux(const BinaryOp& func) const
{
if(EIGEN_UNROLLED_LOOPS
&& SizeAtCompileTime != Dynamic
&& SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT)
return ei_redux_unroller<BinaryOp, Derived, 0,
(SizeAtCompileTime>0 && SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT) ?
SizeAtCompileTime : Dynamic>::run(derived(), func);
else
{
Scalar res;
res = coeff(0,0);
for(int i = 1; i < rows(); i++)
res = func(res, coeff(i, 0));
for(int j = 1; j < cols(); j++)
for(int i = 0; i < rows(); i++)
res = func(res, coeff(i, j));
return res;
}
}
/** \returns the sum of all coefficients of *this
*
* \sa trace()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::sum() const
{
return this->redux(Eigen::ei_scalar_sum_op());
}
/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal.
*
* \c *this can be any matrix, not necessarily square.
*
* \sa diagonal(), sum()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::trace() const
{
return diagonal().sum();
}
/** \returns the minimum of all coefficients of *this
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::minCoeff() const
{
return this->redux(Eigen::ei_scalar_min_op());
}
/** \returns the maximum of all coefficients of *this
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::maxCoeff() const
{
return this->redux(Eigen::ei_scalar_max_op());
}
#endif // EIGEN_REDUX_H

View File

@ -1,102 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
//
// 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 <http://www.gnu.org/licenses/>.
#ifndef EIGEN_SUMOFCOEFFS_H
#define EIGEN_SUMOFCOEFFS_H
template<int Index, int Size, typename Derived>
struct ei_sumofcoeffs_unroller
{
static void run(const Derived &v1, typename Derived::Scalar &dot)
{
ei_sumofcoeffs_unroller<Index-1, Size, Derived>::run(v1, dot);
dot += v1.coeff(Index);
}
};
template<int Size, typename Derived>
struct ei_sumofcoeffs_unroller<0, Size, Derived>
{
static void run(const Derived &v1, typename Derived::Scalar &dot)
{
dot = v1.coeff(0);
}
};
template<int Index, typename Derived>
struct ei_sumofcoeffs_unroller<Index, Dynamic, Derived>
{
static void run(const Derived&, typename Derived::Scalar&) {}
};
// prevent buggy user code from causing an infinite recursion
template<int Index, typename Derived>
struct ei_sumofcoeffs_unroller<Index, 0, Derived>
{
static void run(const Derived&, typename Derived::Scalar&)
{}
};
/** \returns the sum of all coefficients of *this
*
* \only_for_vectors
*
* \sa trace()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::sum() const
{
assert(IsVectorAtCompileTime);
Scalar res;
if(EIGEN_UNROLLED_LOOPS
&& SizeAtCompileTime != Dynamic
&& SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT)
ei_sumofcoeffs_unroller<SizeAtCompileTime-1,
SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT ? SizeAtCompileTime : Dynamic,
Derived>
::run(derived(),res);
else
{
res = coeff(0);
for(int i = 1; i < size(); i++)
res += coeff(i);
}
return res;
}
/** \returns the trace of \c *this, i.e. the sum of the coefficients on the main diagonal.
*
* \c *this can be any matrix, not necessarily square.
*
* \sa diagonal(), sum()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::trace() const
{
return diagonal().sum();
}
#endif // EIGEN_SUMOFCOEFFS_H

View File

@ -120,6 +120,8 @@ const int RowMajor = 1;
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
enum DirectionType { Vertical, Horizontal };
// just a workaround because GCC seems to not really like empty structs
#ifdef __GNUG__
struct ei_empty_struct{char _ei_dummy_;};

182
Eigen/src/Core/Visitor.h Normal file
View File

@ -0,0 +1,182 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// 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 <http://www.gnu.org/licenses/>.
#ifndef EIGEN_VISITOR_H
#define EIGEN_VISITOR_H
template<typename Visitor, typename Derived, int UnrollCount>
struct ei_visitor_unroller
{
enum {
col = (UnrollCount-1) / Derived::RowsAtCompileTime,
row = (UnrollCount-1) % Derived::RowsAtCompileTime
};
static void run(const Derived &mat, Visitor& visitor)
{
ei_visitor_unroller<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
visitor(mat.coeff(row, col), row, col);
}
};
template<typename Visitor, typename Derived>
struct ei_visitor_unroller<Visitor, Derived, 1>
{
static void run(const Derived &mat, Visitor& visitor)
{
return visitor.init(mat.coeff(0, 0), 0, 0);
}
};
template<typename Visitor, typename Derived>
struct ei_visitor_unroller<Visitor, Derived, Dynamic>
{
static void run(const Derived &mat, Visitor& visitor) {}
};
/** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
*
* The template parameter \a Visitor is the type of the visitor and provides the following interface:
* \code
* struct MyVisitor {
* // called for the first coefficient
* void init(const Scalar& value, int i, int j);
* // called for all other coefficients
* void operator() (const Scalar& value, int i, int j);
* };
* \endcode
*
* \sa minCoeff(int*,int*), maxCoeff(int*,int*), MatrixBase::redux()
*/
template<typename Derived>
template<typename Visitor>
void MatrixBase<Derived>::visit(Visitor& visitor) const
{
if(EIGEN_UNROLLED_LOOPS
&& SizeAtCompileTime != Dynamic
&& SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT)
return ei_visitor_unroller<Visitor, Derived,
(SizeAtCompileTime>0 && SizeAtCompileTime <= EIGEN_UNROLLING_LIMIT) ?
SizeAtCompileTime : Dynamic>::run(derived(), visitor);
else
{
Scalar res;
visitor.init(coeff(0,0), 0, 0);
for(int i = 1; i < rows(); i++)
visitor(res, coeff(i, 0), i, 0);
for(int j = 1; j < cols(); j++)
for(int i = 0; i < rows(); i++)
visitor(res, coeff(i, j), i, j);
}
}
/** \internal
* \brief Base class to implement min and max visitors
*/
template <typename Scalar>
struct ei_coeff_visitor
{
int row, col;
Scalar res;
void init(const Scalar& value, int i, int j)
{
res = value;
row = i;
col = j;
}
};
/** \internal
* \brief Visitor computing the min coefficient with its value and coordinates
*
* \sa ei_coeff_visitor, ei_max_coeff_visitor, MatrixBase::minCoeff(int*, int*)
*/
template <typename Scalar>
struct ei_min_coeff_visitor : ei_coeff_visitor<Scalar>
{
void operator() (const Scalar& value, int i, int j)
{
if(value < this->res)
{
this->res = value;
this->row = i;
this->col = j;
}
}
};
/** \internal
* \brief Visitor computing the max coefficient with its value and coordinates
*
* \sa ei_coeff_visitor, ei_min_coeff_visitor, MatrixBase::maxCoeff(int*, int*)
*/
template <typename Scalar>
struct ei_max_coeff_visitor : ei_coeff_visitor<Scalar>
{
void operator() (const Scalar& value, int i, int j)
{
if(value > this->res)
{
this->res = value;
this->row = i;
this->col = j;
}
}
};
/** \returns the minimum of all coefficients of *this
* and puts in *row and *col its location.
*
* \sa MatrixBase::maxCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::minCoeff()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::minCoeff(int* row, int* col) const
{
ei_min_coeff_visitor<Scalar> minVisitor;
this->visit(minVisitor);
*row = minVisitor.row;
if (col) *col = minVisitor.col;
return minVisitor.res;
}
/** \returns the maximum of all coefficients of *this
* and puts in *row and *col its location.
*
* \sa MatrixBase::minCoeff(int*,int*), MatrixBase::visitor(), MatrixBase::maxCoeff()
*/
template<typename Derived>
typename ei_traits<Derived>::Scalar
MatrixBase<Derived>::maxCoeff(int* row, int* col) const
{
ei_max_coeff_visitor<Scalar> maxVisitor;
this->visit(maxVisitor);
*row = maxVisitor.row;
if (col) *col = maxVisitor.col;
return maxVisitor.res;
}
#endif // EIGEN_VISITOR_H