cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

Visitor.h (11997B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_VISITOR_H
     11 #define EIGEN_VISITOR_H
     12 
     13 namespace Eigen {
     14 
     15 namespace internal {
     16 
     17 template<typename Visitor, typename Derived, int UnrollCount>
     18 struct visitor_impl
     19 {
     20   enum {
     21     col = (UnrollCount-1) / Derived::RowsAtCompileTime,
     22     row = (UnrollCount-1) % Derived::RowsAtCompileTime
     23   };
     24 
     25   EIGEN_DEVICE_FUNC
     26   static inline void run(const Derived &mat, Visitor& visitor)
     27   {
     28     visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
     29     visitor(mat.coeff(row, col), row, col);
     30   }
     31 };
     32 
     33 template<typename Visitor, typename Derived>
     34 struct visitor_impl<Visitor, Derived, 1>
     35 {
     36   EIGEN_DEVICE_FUNC
     37   static inline void run(const Derived &mat, Visitor& visitor)
     38   {
     39     return visitor.init(mat.coeff(0, 0), 0, 0);
     40   }
     41 };
     42 
     43 // This specialization enables visitors on empty matrices at compile-time
     44 template<typename Visitor, typename Derived>
     45 struct visitor_impl<Visitor, Derived, 0> {
     46   EIGEN_DEVICE_FUNC
     47   static inline void run(const Derived &/*mat*/, Visitor& /*visitor*/)
     48   {}
     49 };
     50 
     51 template<typename Visitor, typename Derived>
     52 struct visitor_impl<Visitor, Derived, Dynamic>
     53 {
     54   EIGEN_DEVICE_FUNC
     55   static inline void run(const Derived& mat, Visitor& visitor)
     56   {
     57     visitor.init(mat.coeff(0,0), 0, 0);
     58     for(Index i = 1; i < mat.rows(); ++i)
     59       visitor(mat.coeff(i, 0), i, 0);
     60     for(Index j = 1; j < mat.cols(); ++j)
     61       for(Index i = 0; i < mat.rows(); ++i)
     62         visitor(mat.coeff(i, j), i, j);
     63   }
     64 };
     65 
     66 // evaluator adaptor
     67 template<typename XprType>
     68 class visitor_evaluator
     69 {
     70 public:
     71   EIGEN_DEVICE_FUNC
     72   explicit visitor_evaluator(const XprType &xpr) : m_evaluator(xpr), m_xpr(xpr) {}
     73 
     74   typedef typename XprType::Scalar Scalar;
     75   typedef typename XprType::CoeffReturnType CoeffReturnType;
     76 
     77   enum {
     78     RowsAtCompileTime = XprType::RowsAtCompileTime,
     79     CoeffReadCost = internal::evaluator<XprType>::CoeffReadCost
     80   };
     81 
     82   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
     83   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
     84   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_xpr.size(); }
     85 
     86   EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index row, Index col) const
     87   { return m_evaluator.coeff(row, col); }
     88 
     89 protected:
     90   internal::evaluator<XprType> m_evaluator;
     91   const XprType &m_xpr;
     92 };
     93 } // end namespace internal
     94 
     95 /** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
     96   *
     97   * The template parameter \a Visitor is the type of the visitor and provides the following interface:
     98   * \code
     99   * struct MyVisitor {
    100   *   // called for the first coefficient
    101   *   void init(const Scalar& value, Index i, Index j);
    102   *   // called for all other coefficients
    103   *   void operator() (const Scalar& value, Index i, Index j);
    104   * };
    105   * \endcode
    106   *
    107   * \note compared to one or two \em for \em loops, visitors offer automatic
    108   * unrolling for small fixed size matrix.
    109   *
    110   * \note if the matrix is empty, then the visitor is left unchanged.
    111   *
    112   * \sa minCoeff(Index*,Index*), maxCoeff(Index*,Index*), DenseBase::redux()
    113   */
    114 template<typename Derived>
    115 template<typename Visitor>
    116 EIGEN_DEVICE_FUNC
    117 void DenseBase<Derived>::visit(Visitor& visitor) const
    118 {
    119   if(size()==0)
    120     return;
    121 
    122   typedef typename internal::visitor_evaluator<Derived> ThisEvaluator;
    123   ThisEvaluator thisEval(derived());
    124 
    125   enum {
    126     unroll =  SizeAtCompileTime != Dynamic
    127            && SizeAtCompileTime * int(ThisEvaluator::CoeffReadCost) + (SizeAtCompileTime-1) * int(internal::functor_traits<Visitor>::Cost) <= EIGEN_UNROLLING_LIMIT
    128   };
    129   return internal::visitor_impl<Visitor, ThisEvaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(thisEval, visitor);
    130 }
    131 
    132 namespace internal {
    133 
    134 /** \internal
    135   * \brief Base class to implement min and max visitors
    136   */
    137 template <typename Derived>
    138 struct coeff_visitor
    139 {
    140   // default initialization to avoid countless invalid maybe-uninitialized warnings by gcc
    141   EIGEN_DEVICE_FUNC
    142   coeff_visitor() : row(-1), col(-1), res(0) {}
    143   typedef typename Derived::Scalar Scalar;
    144   Index row, col;
    145   Scalar res;
    146   EIGEN_DEVICE_FUNC
    147   inline void init(const Scalar& value, Index i, Index j)
    148   {
    149     res = value;
    150     row = i;
    151     col = j;
    152   }
    153 };
    154 
    155 /** \internal
    156   * \brief Visitor computing the min coefficient with its value and coordinates
    157   *
    158   * \sa DenseBase::minCoeff(Index*, Index*)
    159   */
    160 template <typename Derived, int NaNPropagation>
    161 struct min_coeff_visitor : coeff_visitor<Derived>
    162 {
    163   typedef typename Derived::Scalar Scalar;
    164   EIGEN_DEVICE_FUNC
    165   void operator() (const Scalar& value, Index i, Index j)
    166   {
    167     if(value < this->res)
    168     {
    169       this->res = value;
    170       this->row = i;
    171       this->col = j;
    172     }
    173   }
    174 };
    175 
    176 template <typename Derived>
    177 struct min_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
    178 {
    179   typedef typename Derived::Scalar Scalar;
    180   EIGEN_DEVICE_FUNC
    181   void operator() (const Scalar& value, Index i, Index j)
    182   {
    183     if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value < this->res))
    184     {
    185       this->res = value;
    186       this->row = i;
    187       this->col = j;
    188     }
    189   }
    190 };
    191 
    192 template <typename Derived>
    193 struct min_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
    194 {
    195   typedef typename Derived::Scalar Scalar;
    196   EIGEN_DEVICE_FUNC
    197   void operator() (const Scalar& value, Index i, Index j)
    198   {
    199     if((numext::isnan)(value) || value < this->res)
    200     {
    201       this->res = value;
    202       this->row = i;
    203       this->col = j;
    204     }
    205   }
    206 };
    207 
    208 template<typename Scalar, int NaNPropagation>
    209     struct functor_traits<min_coeff_visitor<Scalar, NaNPropagation> > {
    210   enum {
    211     Cost = NumTraits<Scalar>::AddCost
    212   };
    213 };
    214 
    215 /** \internal
    216   * \brief Visitor computing the max coefficient with its value and coordinates
    217   *
    218   * \sa DenseBase::maxCoeff(Index*, Index*)
    219   */
    220 template <typename Derived, int NaNPropagation>
    221 struct max_coeff_visitor : coeff_visitor<Derived>
    222 {
    223   typedef typename Derived::Scalar Scalar;
    224   EIGEN_DEVICE_FUNC
    225   void operator() (const Scalar& value, Index i, Index j)
    226   {
    227     if(value > this->res)
    228     {
    229       this->res = value;
    230       this->row = i;
    231       this->col = j;
    232     }
    233   }
    234 };
    235 
    236 template <typename Derived>
    237 struct max_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
    238 {
    239   typedef typename Derived::Scalar Scalar;
    240   EIGEN_DEVICE_FUNC
    241   void operator() (const Scalar& value, Index i, Index j)
    242   {
    243     if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value > this->res))
    244     {
    245       this->res = value;
    246       this->row = i;
    247       this->col = j;
    248     }
    249   }
    250 };
    251 
    252 template <typename Derived>
    253 struct max_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
    254 {
    255   typedef typename Derived::Scalar Scalar;
    256   EIGEN_DEVICE_FUNC
    257   void operator() (const Scalar& value, Index i, Index j)
    258   {
    259     if((numext::isnan)(value) || value > this->res)
    260     {
    261       this->res = value;
    262       this->row = i;
    263       this->col = j;
    264     }
    265   }
    266 };
    267 
    268 template<typename Scalar, int NaNPropagation>
    269 struct functor_traits<max_coeff_visitor<Scalar, NaNPropagation> > {
    270   enum {
    271     Cost = NumTraits<Scalar>::AddCost
    272   };
    273 };
    274 
    275 } // end namespace internal
    276 
    277 /** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
    278   * \returns the minimum of all coefficients of *this and puts in *row and *col its location.
    279   *
    280   * In case \c *this contains NaN, NaNPropagation determines the behavior:
    281   *   NaNPropagation == PropagateFast : undefined
    282   *   NaNPropagation == PropagateNaN : result is NaN
    283   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
    284   * \warning the matrix must be not empty, otherwise an assertion is triggered.
    285   *
    286   * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
    287   */
    288 template<typename Derived>
    289 template<int NaNPropagation, typename IndexType>
    290 EIGEN_DEVICE_FUNC
    291 typename internal::traits<Derived>::Scalar
    292 DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
    293 {
    294   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
    295 
    296   internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
    297   this->visit(minVisitor);
    298   *rowId = minVisitor.row;
    299   if (colId) *colId = minVisitor.col;
    300   return minVisitor.res;
    301 }
    302 
    303 /** \returns the minimum of all coefficients of *this and puts in *index its location.
    304   *
    305   * In case \c *this contains NaN, NaNPropagation determines the behavior:
    306   *   NaNPropagation == PropagateFast : undefined
    307   *   NaNPropagation == PropagateNaN : result is NaN
    308   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
    309   * \warning the matrix must be not empty, otherwise an assertion is triggered.
    310   *
    311   * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::minCoeff()
    312   */
    313 template<typename Derived>
    314 template<int NaNPropagation, typename IndexType>
    315 EIGEN_DEVICE_FUNC
    316 typename internal::traits<Derived>::Scalar
    317 DenseBase<Derived>::minCoeff(IndexType* index) const
    318 {
    319   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
    320 
    321   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
    322       internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
    323   this->visit(minVisitor);
    324   *index = IndexType((RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row);
    325   return minVisitor.res;
    326 }
    327 
    328 /** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
    329   * \returns the maximum of all coefficients of *this and puts in *row and *col its location.
    330   *
    331   * In case \c *this contains NaN, NaNPropagation determines the behavior:
    332   *   NaNPropagation == PropagateFast : undefined
    333   *   NaNPropagation == PropagateNaN : result is NaN
    334   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
    335   * \warning the matrix must be not empty, otherwise an assertion is triggered.
    336   *
    337   * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
    338   */
    339 template<typename Derived>
    340 template<int NaNPropagation, typename IndexType>
    341 EIGEN_DEVICE_FUNC
    342 typename internal::traits<Derived>::Scalar
    343 DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
    344 {
    345   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
    346 
    347   internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
    348   this->visit(maxVisitor);
    349   *rowPtr = maxVisitor.row;
    350   if (colPtr) *colPtr = maxVisitor.col;
    351   return maxVisitor.res;
    352 }
    353 
    354 /** \returns the maximum of all coefficients of *this and puts in *index its location.
    355   *
    356   * In case \c *this contains NaN, NaNPropagation determines the behavior:
    357   *   NaNPropagation == PropagateFast : undefined
    358   *   NaNPropagation == PropagateNaN : result is NaN
    359   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
    360   * \warning the matrix must be not empty, otherwise an assertion is triggered.
    361   *
    362   * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
    363   */
    364 template<typename Derived>
    365 template<int NaNPropagation, typename IndexType>
    366 EIGEN_DEVICE_FUNC
    367 typename internal::traits<Derived>::Scalar
    368 DenseBase<Derived>::maxCoeff(IndexType* index) const
    369 {
    370   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
    371 
    372   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
    373       internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
    374   this->visit(maxVisitor);
    375   *index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
    376   return maxVisitor.res;
    377 }
    378 
    379 } // end namespace Eigen
    380 
    381 #endif // EIGEN_VISITOR_H