diff options
author | Gael Guennebaud <g.gael@free.fr> | 2008-03-16 14:36:25 +0000 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2008-03-16 14:36:25 +0000 |
commit | 612350e3f85998c25d1155ec4d8a38c623f9457c (patch) | |
tree | 1f6086a94b5b4be8885e67bb275b428d23f9c452 /Eigen/src/Core | |
parent | 29184ad27df1b398d4619dea78d0fb8aee445c1f (diff) |
* 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
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r-- | Eigen/src/Core/AssociativeFunctors.h | 64 | ||||
-rw-r--r-- | Eigen/src/Core/CwiseBinaryOp.h | 42 | ||||
-rw-r--r-- | Eigen/src/Core/ForwardDeclarations.h | 3 | ||||
-rw-r--r-- | Eigen/src/Core/MathFunctions.h | 10 | ||||
-rw-r--r-- | Eigen/src/Core/MatrixBase.h | 59 | ||||
-rw-r--r-- | Eigen/src/Core/Redux.h | 232 | ||||
-rw-r--r-- | Eigen/src/Core/SumOfCoeffs.h | 102 | ||||
-rw-r--r-- | Eigen/src/Core/Util.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/Visitor.h | 182 |
9 files changed, 551 insertions, 145 deletions
diff --git a/Eigen/src/Core/AssociativeFunctors.h b/Eigen/src/Core/AssociativeFunctors.h new file mode 100644 index 000000000..106549f75 --- /dev/null +++ b/Eigen/src/Core/AssociativeFunctors.h @@ -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 diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h index 131e98362..1ab759241 100644 --- a/Eigen/src/Core/CwiseBinaryOp.h +++ b/Eigen/src/Core/CwiseBinaryOp.h @@ -94,15 +94,6 @@ class CwiseBinaryOp : ei_no_assignment_operator, }; /** \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 * * \sa class CwiseBinaryOp, MatrixBase::operator- @@ -112,15 +103,6 @@ struct ei_scalar_difference_op EIGEN_EMPTY_STRUCT { }; /** \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 * * \sa class CwiseBinaryOp, MatrixBase::cwiseQuotient() @@ -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 diff --git a/Eigen/src/Core/ForwardDeclarations.h b/Eigen/src/Core/ForwardDeclarations.h index 69b8cab7b..9e0bbe2e6 100644 --- a/Eigen/src/Core/ForwardDeclarations.h +++ b/Eigen/src/Core/ForwardDeclarations.h @@ -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 { diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 13bd549f4..a1a54cc38 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -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) { diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 95fc05b8e..f3be4977f 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -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); } diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h new file mode 100644 index 000000000..fa1f0e652 --- /dev/null +++ b/Eigen/src/Core/Redux.h @@ -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 diff --git a/Eigen/src/Core/SumOfCoeffs.h b/Eigen/src/Core/SumOfCoeffs.h deleted file mode 100644 index 36e75d3e9..000000000 --- a/Eigen/src/Core/SumOfCoeffs.h +++ /dev/null @@ -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 diff --git a/Eigen/src/Core/Util.h b/Eigen/src/Core/Util.h index 71a8294f6..54c56eb3c 100644 --- a/Eigen/src/Core/Util.h +++ b/Eigen/src/Core/Util.h @@ -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_;}; diff --git a/Eigen/src/Core/Visitor.h b/Eigen/src/Core/Visitor.h new file mode 100644 index 000000000..a3a2ef34e --- /dev/null +++ b/Eigen/src/Core/Visitor.h @@ -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 |