Visitor.h
Go to the documentation of this file.
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 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef EIGEN_VISITOR_H
26 #define EIGEN_VISITOR_H
27 
28 namespace Eigen {
29 
30 namespace internal {
31 
32 template<typename Visitor, typename Derived, int UnrollCount>
33 struct visitor_impl
34 {
35  enum {
36  col = (UnrollCount-1) / Derived::RowsAtCompileTime,
37  row = (UnrollCount-1) % Derived::RowsAtCompileTime
38  };
39 
40  static inline void run(const Derived &mat, Visitor& visitor)
41  {
42  visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
43  visitor(mat.coeff(row, col), row, col);
44  }
45 };
46 
47 template<typename Visitor, typename Derived>
48 struct visitor_impl<Visitor, Derived, 1>
49 {
50  static inline void run(const Derived &mat, Visitor& visitor)
51  {
52  return visitor.init(mat.coeff(0, 0), 0, 0);
53  }
54 };
55 
56 template<typename Visitor, typename Derived>
57 struct visitor_impl<Visitor, Derived, Dynamic>
58 {
59  typedef typename Derived::Index Index;
60  static inline void run(const Derived& mat, Visitor& visitor)
61  {
62  visitor.init(mat.coeff(0,0), 0, 0);
63  for(Index i = 1; i < mat.rows(); ++i)
64  visitor(mat.coeff(i, 0), i, 0);
65  for(Index j = 1; j < mat.cols(); ++j)
66  for(Index i = 0; i < mat.rows(); ++i)
67  visitor(mat.coeff(i, j), i, j);
68  }
69 };
70 
71 } // end namespace internal
72 
90 template<typename Derived>
91 template<typename Visitor>
92 void DenseBase<Derived>::visit(Visitor& visitor) const
93 {
94  enum { unroll = SizeAtCompileTime != Dynamic
95  && CoeffReadCost != Dynamic
96  && (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
97  && SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
99  return internal::visitor_impl<Visitor, Derived,
100  unroll ? int(SizeAtCompileTime) : Dynamic
101  >::run(derived(), visitor);
102 }
103 
104 namespace internal {
105 
109 template <typename Derived>
110 struct coeff_visitor
111 {
112  typedef typename Derived::Index Index;
113  typedef typename Derived::Scalar Scalar;
114  Index row, col;
115  Scalar res;
116  inline void init(const Scalar& value, Index i, Index j)
117  {
118  res = value;
119  row = i;
120  col = j;
121  }
122 };
123 
129 template <typename Derived>
130 struct min_coeff_visitor : coeff_visitor<Derived>
131 {
132  typedef typename Derived::Index Index;
133  typedef typename Derived::Scalar Scalar;
134  void operator() (const Scalar& value, Index i, Index j)
135  {
136  if(value < this->res)
137  {
138  this->res = value;
139  this->row = i;
140  this->col = j;
141  }
142  }
143 };
144 
145 template<typename Scalar>
146 struct functor_traits<min_coeff_visitor<Scalar> > {
147  enum {
149  };
150 };
151 
157 template <typename Derived>
158 struct max_coeff_visitor : coeff_visitor<Derived>
159 {
160  typedef typename Derived::Index Index;
161  typedef typename Derived::Scalar Scalar;
162  void operator() (const Scalar& value, Index i, Index j)
163  {
164  if(value > this->res)
165  {
166  this->res = value;
167  this->row = i;
168  this->col = j;
169  }
170  }
171 };
172 
173 template<typename Scalar>
174 struct functor_traits<max_coeff_visitor<Scalar> > {
175  enum {
177  };
178 };
179 
180 } // end namespace internal
181 
187 template<typename Derived>
188 template<typename IndexType>
189 typename internal::traits<Derived>::Scalar
190 DenseBase<Derived>::minCoeff(IndexType* row, IndexType* col) const
191 {
192  internal::min_coeff_visitor<Derived> minVisitor;
193  this->visit(minVisitor);
194  *row = minVisitor.row;
195  if (col) *col = minVisitor.col;
196  return minVisitor.res;
197 }
198 
204 template<typename Derived>
205 template<typename IndexType>
206 typename internal::traits<Derived>::Scalar
207 DenseBase<Derived>::minCoeff(IndexType* index) const
208 {
210  internal::min_coeff_visitor<Derived> minVisitor;
211  this->visit(minVisitor);
212  *index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
213  return minVisitor.res;
214 }
215 
221 template<typename Derived>
222 template<typename IndexType>
223 typename internal::traits<Derived>::Scalar
224 DenseBase<Derived>::maxCoeff(IndexType* row, IndexType* col) const
225 {
226  internal::max_coeff_visitor<Derived> maxVisitor;
227  this->visit(maxVisitor);
228  *row = maxVisitor.row;
229  if (col) *col = maxVisitor.col;
230  return maxVisitor.res;
231 }
232 
238 template<typename Derived>
239 template<typename IndexType>
240 typename internal::traits<Derived>::Scalar
241 DenseBase<Derived>::maxCoeff(IndexType* index) const
242 {
244  internal::max_coeff_visitor<Derived> maxVisitor;
245  this->visit(maxVisitor);
246  *index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
247  return maxVisitor.res;
248 }
249 
250 } // end namespace Eigen
251 
252 #endif // EIGEN_VISITOR_H