Visitor.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #ifndef EIGEN_VISITOR_H
00026 #define EIGEN_VISITOR_H
00027 
00028 namespace Eigen { 
00029 
00030 namespace internal {
00031 
00032 template<typename Visitor, typename Derived, int UnrollCount>
00033 struct visitor_impl
00034 {
00035   enum {
00036     col = (UnrollCount-1) / Derived::RowsAtCompileTime,
00037     row = (UnrollCount-1) % Derived::RowsAtCompileTime
00038   };
00039 
00040   static inline void run(const Derived &mat, Visitor& visitor)
00041   {
00042     visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
00043     visitor(mat.coeff(row, col), row, col);
00044   }
00045 };
00046 
00047 template<typename Visitor, typename Derived>
00048 struct visitor_impl<Visitor, Derived, 1>
00049 {
00050   static inline void run(const Derived &mat, Visitor& visitor)
00051   {
00052     return visitor.init(mat.coeff(0, 0), 0, 0);
00053   }
00054 };
00055 
00056 template<typename Visitor, typename Derived>
00057 struct visitor_impl<Visitor, Derived, Dynamic>
00058 {
00059   typedef typename Derived::Index Index;
00060   static inline void run(const Derived& mat, Visitor& visitor)
00061   {
00062     visitor.init(mat.coeff(0,0), 0, 0);
00063     for(Index i = 1; i < mat.rows(); ++i)
00064       visitor(mat.coeff(i, 0), i, 0);
00065     for(Index j = 1; j < mat.cols(); ++j)
00066       for(Index i = 0; i < mat.rows(); ++i)
00067         visitor(mat.coeff(i, j), i, j);
00068   }
00069 };
00070 
00071 } // end namespace internal
00072 
00090 template<typename Derived>
00091 template<typename Visitor>
00092 void DenseBase<Derived>::visit(Visitor& visitor) const
00093 {
00094   enum { unroll = SizeAtCompileTime != Dynamic
00095                    && CoeffReadCost != Dynamic
00096                    && (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
00097                    && SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
00098                       <= EIGEN_UNROLLING_LIMIT };
00099   return internal::visitor_impl<Visitor, Derived,
00100       unroll ? int(SizeAtCompileTime) : Dynamic
00101     >::run(derived(), visitor);
00102 }
00103 
00104 namespace internal {
00105 
00109 template <typename Derived>
00110 struct coeff_visitor
00111 {
00112   typedef typename Derived::Index Index;
00113   typedef typename Derived::Scalar Scalar;
00114   Index row, col;
00115   Scalar res;
00116   inline void init(const Scalar& value, Index i, Index j)
00117   {
00118     res = value;
00119     row = i;
00120     col = j;
00121   }
00122 };
00123 
00129 template <typename Derived>
00130 struct min_coeff_visitor : coeff_visitor<Derived>
00131 {
00132   typedef typename Derived::Index Index;
00133   typedef typename Derived::Scalar Scalar;
00134   void operator() (const Scalar& value, Index i, Index j)
00135   {
00136     if(value < this->res)
00137     {
00138       this->res = value;
00139       this->row = i;
00140       this->col = j;
00141     }
00142   }
00143 };
00144 
00145 template<typename Scalar>
00146 struct functor_traits<min_coeff_visitor<Scalar> > {
00147   enum {
00148     Cost = NumTraits<Scalar>::AddCost
00149   };
00150 };
00151 
00157 template <typename Derived>
00158 struct max_coeff_visitor : coeff_visitor<Derived>
00159 {
00160   typedef typename Derived::Index Index;
00161   typedef typename Derived::Scalar Scalar;
00162   void operator() (const Scalar& value, Index i, Index j)
00163   {
00164     if(value > this->res)
00165     {
00166       this->res = value;
00167       this->row = i;
00168       this->col = j;
00169     }
00170   }
00171 };
00172 
00173 template<typename Scalar>
00174 struct functor_traits<max_coeff_visitor<Scalar> > {
00175   enum {
00176     Cost = NumTraits<Scalar>::AddCost
00177   };
00178 };
00179 
00180 } // end namespace internal
00181 
00187 template<typename Derived>
00188 template<typename IndexType>
00189 typename internal::traits<Derived>::Scalar
00190 DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
00191 {
00192   internal::min_coeff_visitor<Derived> minVisitor;
00193   this->visit(minVisitor);
00194   *row = minVisitor.row;
00195   if (col) *col = minVisitor.col;
00196   return minVisitor.res;
00197 }
00198 
00204 template<typename Derived>
00205 template<typename IndexType>
00206 typename internal::traits<Derived>::Scalar
00207 DenseBase<Derived>::minCoeff(IndexType* index) const
00208 {
00209   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
00210   internal::min_coeff_visitor<Derived> minVisitor;
00211   this->visit(minVisitor);
00212   *index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
00213   return minVisitor.res;
00214 }
00215 
00221 template<typename Derived>
00222 template<typename IndexType>
00223 typename internal::traits<Derived>::Scalar
00224 DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
00225 {
00226   internal::max_coeff_visitor<Derived> maxVisitor;
00227   this->visit(maxVisitor);
00228   *row = maxVisitor.row;
00229   if (col) *col = maxVisitor.col;
00230   return maxVisitor.res;
00231 }
00232 
00238 template<typename Derived>
00239 template<typename IndexType>
00240 typename internal::traits<Derived>::Scalar
00241 DenseBase<Derived>::maxCoeff(IndexType* index) const
00242 {
00243   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
00244   internal::max_coeff_visitor<Derived> maxVisitor;
00245   this->visit(maxVisitor);
00246   *index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
00247   return maxVisitor.res;
00248 }
00249 
00250 } // end namespace Eigen
00251 
00252 #endif // EIGEN_VISITOR_H