Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:56:19

0001 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
0005 //
0006 // This Source Code Form is subject to the terms of the Mozilla
0007 // Public License v. 2.0. If a copy of the MPL was not distributed
0008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0009 
0010 #ifndef EIGEN_VISITOR_H
0011 #define EIGEN_VISITOR_H
0012 
0013 namespace Eigen {
0014 
0015 namespace internal {
0016 
0017 template<typename Visitor, typename Derived, int UnrollCount>
0018 struct visitor_impl
0019 {
0020   enum {
0021     col = (UnrollCount-1) / Derived::RowsAtCompileTime,
0022     row = (UnrollCount-1) % Derived::RowsAtCompileTime
0023   };
0024 
0025   EIGEN_DEVICE_FUNC
0026   static inline void run(const Derived &mat, Visitor& visitor)
0027   {
0028     visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
0029     visitor(mat.coeff(row, col), row, col);
0030   }
0031 };
0032 
0033 template<typename Visitor, typename Derived>
0034 struct visitor_impl<Visitor, Derived, 1>
0035 {
0036   EIGEN_DEVICE_FUNC
0037   static inline void run(const Derived &mat, Visitor& visitor)
0038   {
0039     return visitor.init(mat.coeff(0, 0), 0, 0);
0040   }
0041 };
0042 
0043 // This specialization enables visitors on empty matrices at compile-time
0044 template<typename Visitor, typename Derived>
0045 struct visitor_impl<Visitor, Derived, 0> {
0046   EIGEN_DEVICE_FUNC
0047   static inline void run(const Derived &/*mat*/, Visitor& /*visitor*/)
0048   {}
0049 };
0050 
0051 template<typename Visitor, typename Derived>
0052 struct visitor_impl<Visitor, Derived, Dynamic>
0053 {
0054   EIGEN_DEVICE_FUNC
0055   static inline void run(const Derived& mat, Visitor& visitor)
0056   {
0057     visitor.init(mat.coeff(0,0), 0, 0);
0058     for(Index i = 1; i < mat.rows(); ++i)
0059       visitor(mat.coeff(i, 0), i, 0);
0060     for(Index j = 1; j < mat.cols(); ++j)
0061       for(Index i = 0; i < mat.rows(); ++i)
0062         visitor(mat.coeff(i, j), i, j);
0063   }
0064 };
0065 
0066 // evaluator adaptor
0067 template<typename XprType>
0068 class visitor_evaluator
0069 {
0070 public:
0071   EIGEN_DEVICE_FUNC
0072   explicit visitor_evaluator(const XprType &xpr) : m_evaluator(xpr), m_xpr(xpr) {}
0073 
0074   typedef typename XprType::Scalar Scalar;
0075   typedef typename XprType::CoeffReturnType CoeffReturnType;
0076 
0077   enum {
0078     RowsAtCompileTime = XprType::RowsAtCompileTime,
0079     CoeffReadCost = internal::evaluator<XprType>::CoeffReadCost
0080   };
0081 
0082   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_xpr.rows(); }
0083   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_xpr.cols(); }
0084   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_xpr.size(); }
0085 
0086   EIGEN_DEVICE_FUNC CoeffReturnType coeff(Index row, Index col) const
0087   { return m_evaluator.coeff(row, col); }
0088 
0089 protected:
0090   internal::evaluator<XprType> m_evaluator;
0091   const XprType &m_xpr;
0092 };
0093 } // end namespace internal
0094 
0095 /** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
0096   *
0097   * The template parameter \a Visitor is the type of the visitor and provides the following interface:
0098   * \code
0099   * struct MyVisitor {
0100   *   // called for the first coefficient
0101   *   void init(const Scalar& value, Index i, Index j);
0102   *   // called for all other coefficients
0103   *   void operator() (const Scalar& value, Index i, Index j);
0104   * };
0105   * \endcode
0106   *
0107   * \note compared to one or two \em for \em loops, visitors offer automatic
0108   * unrolling for small fixed size matrix.
0109   *
0110   * \note if the matrix is empty, then the visitor is left unchanged.
0111   *
0112   * \sa minCoeff(Index*,Index*), maxCoeff(Index*,Index*), DenseBase::redux()
0113   */
0114 template<typename Derived>
0115 template<typename Visitor>
0116 EIGEN_DEVICE_FUNC
0117 void DenseBase<Derived>::visit(Visitor& visitor) const
0118 {
0119   if(size()==0)
0120     return;
0121 
0122   typedef typename internal::visitor_evaluator<Derived> ThisEvaluator;
0123   ThisEvaluator thisEval(derived());
0124 
0125   enum {
0126     unroll =  SizeAtCompileTime != Dynamic
0127            && SizeAtCompileTime * int(ThisEvaluator::CoeffReadCost) + (SizeAtCompileTime-1) * int(internal::functor_traits<Visitor>::Cost) <= EIGEN_UNROLLING_LIMIT
0128   };
0129   return internal::visitor_impl<Visitor, ThisEvaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(thisEval, visitor);
0130 }
0131 
0132 namespace internal {
0133 
0134 /** \internal
0135   * \brief Base class to implement min and max visitors
0136   */
0137 template <typename Derived>
0138 struct coeff_visitor
0139 {
0140   // default initialization to avoid countless invalid maybe-uninitialized warnings by gcc
0141   EIGEN_DEVICE_FUNC
0142   coeff_visitor() : row(-1), col(-1), res(0) {}
0143   typedef typename Derived::Scalar Scalar;
0144   Index row, col;
0145   Scalar res;
0146   EIGEN_DEVICE_FUNC
0147   inline void init(const Scalar& value, Index i, Index j)
0148   {
0149     res = value;
0150     row = i;
0151     col = j;
0152   }
0153 };
0154 
0155 /** \internal
0156   * \brief Visitor computing the min coefficient with its value and coordinates
0157   *
0158   * \sa DenseBase::minCoeff(Index*, Index*)
0159   */
0160 template <typename Derived, int NaNPropagation>
0161 struct min_coeff_visitor : coeff_visitor<Derived>
0162 {
0163   typedef typename Derived::Scalar Scalar;
0164   EIGEN_DEVICE_FUNC
0165   void operator() (const Scalar& value, Index i, Index j)
0166   {
0167     if(value < this->res)
0168     {
0169       this->res = value;
0170       this->row = i;
0171       this->col = j;
0172     }
0173   }
0174 };
0175 
0176 template <typename Derived>
0177 struct min_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
0178 {
0179   typedef typename Derived::Scalar Scalar;
0180   EIGEN_DEVICE_FUNC
0181   void operator() (const Scalar& value, Index i, Index j)
0182   {
0183     if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value < this->res))
0184     {
0185       this->res = value;
0186       this->row = i;
0187       this->col = j;
0188     }
0189   }
0190 };
0191 
0192 template <typename Derived>
0193 struct min_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
0194 {
0195   typedef typename Derived::Scalar Scalar;
0196   EIGEN_DEVICE_FUNC
0197   void operator() (const Scalar& value, Index i, Index j)
0198   {
0199     if((numext::isnan)(value) || value < this->res)
0200     {
0201       this->res = value;
0202       this->row = i;
0203       this->col = j;
0204     }
0205   }
0206 };
0207 
0208 template<typename Scalar, int NaNPropagation>
0209     struct functor_traits<min_coeff_visitor<Scalar, NaNPropagation> > {
0210   enum {
0211     Cost = NumTraits<Scalar>::AddCost
0212   };
0213 };
0214 
0215 /** \internal
0216   * \brief Visitor computing the max coefficient with its value and coordinates
0217   *
0218   * \sa DenseBase::maxCoeff(Index*, Index*)
0219   */
0220 template <typename Derived, int NaNPropagation>
0221 struct max_coeff_visitor : coeff_visitor<Derived>
0222 {
0223   typedef typename Derived::Scalar Scalar;
0224   EIGEN_DEVICE_FUNC
0225   void operator() (const Scalar& value, Index i, Index j)
0226   {
0227     if(value > this->res)
0228     {
0229       this->res = value;
0230       this->row = i;
0231       this->col = j;
0232     }
0233   }
0234 };
0235 
0236 template <typename Derived>
0237 struct max_coeff_visitor<Derived, PropagateNumbers> : coeff_visitor<Derived>
0238 {
0239   typedef typename Derived::Scalar Scalar;
0240   EIGEN_DEVICE_FUNC
0241   void operator() (const Scalar& value, Index i, Index j)
0242   {
0243     if((numext::isnan)(this->res) || (!(numext::isnan)(value) && value > this->res))
0244     {
0245       this->res = value;
0246       this->row = i;
0247       this->col = j;
0248     }
0249   }
0250 };
0251 
0252 template <typename Derived>
0253 struct max_coeff_visitor<Derived, PropagateNaN> : coeff_visitor<Derived>
0254 {
0255   typedef typename Derived::Scalar Scalar;
0256   EIGEN_DEVICE_FUNC
0257   void operator() (const Scalar& value, Index i, Index j)
0258   {
0259     if((numext::isnan)(value) || value > this->res)
0260     {
0261       this->res = value;
0262       this->row = i;
0263       this->col = j;
0264     }
0265   }
0266 };
0267 
0268 template<typename Scalar, int NaNPropagation>
0269 struct functor_traits<max_coeff_visitor<Scalar, NaNPropagation> > {
0270   enum {
0271     Cost = NumTraits<Scalar>::AddCost
0272   };
0273 };
0274 
0275 } // end namespace internal
0276 
0277 /** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
0278   * \returns the minimum of all coefficients of *this and puts in *row and *col its location.
0279   *
0280   * In case \c *this contains NaN, NaNPropagation determines the behavior:
0281   *   NaNPropagation == PropagateFast : undefined
0282   *   NaNPropagation == PropagateNaN : result is NaN
0283   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
0284   * \warning the matrix must be not empty, otherwise an assertion is triggered.
0285   *
0286   * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
0287   */
0288 template<typename Derived>
0289 template<int NaNPropagation, typename IndexType>
0290 EIGEN_DEVICE_FUNC
0291 typename internal::traits<Derived>::Scalar
0292 DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
0293 {
0294   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
0295 
0296   internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
0297   this->visit(minVisitor);
0298   *rowId = minVisitor.row;
0299   if (colId) *colId = minVisitor.col;
0300   return minVisitor.res;
0301 }
0302 
0303 /** \returns the minimum of all coefficients of *this and puts in *index its location.
0304   *
0305   * In case \c *this contains NaN, NaNPropagation determines the behavior:
0306   *   NaNPropagation == PropagateFast : undefined
0307   *   NaNPropagation == PropagateNaN : result is NaN
0308   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
0309   * \warning the matrix must be not empty, otherwise an assertion is triggered.
0310   *
0311   * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::minCoeff()
0312   */
0313 template<typename Derived>
0314 template<int NaNPropagation, typename IndexType>
0315 EIGEN_DEVICE_FUNC
0316 typename internal::traits<Derived>::Scalar
0317 DenseBase<Derived>::minCoeff(IndexType* index) const
0318 {
0319   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
0320 
0321   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
0322       internal::min_coeff_visitor<Derived, NaNPropagation> minVisitor;
0323   this->visit(minVisitor);
0324   *index = IndexType((RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row);
0325   return minVisitor.res;
0326 }
0327 
0328 /** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
0329   * \returns the maximum of all coefficients of *this and puts in *row and *col its location.
0330   *
0331   * In case \c *this contains NaN, NaNPropagation determines the behavior:
0332   *   NaNPropagation == PropagateFast : undefined
0333   *   NaNPropagation == PropagateNaN : result is NaN
0334   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
0335   * \warning the matrix must be not empty, otherwise an assertion is triggered.
0336   *
0337   * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
0338   */
0339 template<typename Derived>
0340 template<int NaNPropagation, typename IndexType>
0341 EIGEN_DEVICE_FUNC
0342 typename internal::traits<Derived>::Scalar
0343 DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
0344 {
0345   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
0346 
0347   internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
0348   this->visit(maxVisitor);
0349   *rowPtr = maxVisitor.row;
0350   if (colPtr) *colPtr = maxVisitor.col;
0351   return maxVisitor.res;
0352 }
0353 
0354 /** \returns the maximum of all coefficients of *this and puts in *index its location.
0355   *
0356   * In case \c *this contains NaN, NaNPropagation determines the behavior:
0357   *   NaNPropagation == PropagateFast : undefined
0358   *   NaNPropagation == PropagateNaN : result is NaN
0359   *   NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN
0360   * \warning the matrix must be not empty, otherwise an assertion is triggered.
0361   *
0362   * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
0363   */
0364 template<typename Derived>
0365 template<int NaNPropagation, typename IndexType>
0366 EIGEN_DEVICE_FUNC
0367 typename internal::traits<Derived>::Scalar
0368 DenseBase<Derived>::maxCoeff(IndexType* index) const
0369 {
0370   eigen_assert(this->rows()>0 && this->cols()>0 && "you are using an empty matrix");
0371 
0372   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
0373       internal::max_coeff_visitor<Derived, NaNPropagation> maxVisitor;
0374   this->visit(maxVisitor);
0375   *index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
0376   return maxVisitor.res;
0377 }
0378 
0379 } // end namespace Eigen
0380 
0381 #endif // EIGEN_VISITOR_H