blob: 64867b7a2cbff3f990c3442085938c3b80c047cc [file] [log] [blame]
Narayan Kamathc981c482012-11-02 10:59:05 +00001// 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
13namespace Eigen {
14
15namespace internal {
16
17template<typename Visitor, typename Derived, int UnrollCount>
18struct visitor_impl
19{
20 enum {
21 col = (UnrollCount-1) / Derived::RowsAtCompileTime,
22 row = (UnrollCount-1) % Derived::RowsAtCompileTime
23 };
24
25 static inline void run(const Derived &mat, Visitor& visitor)
26 {
27 visitor_impl<Visitor, Derived, UnrollCount-1>::run(mat, visitor);
28 visitor(mat.coeff(row, col), row, col);
29 }
30};
31
32template<typename Visitor, typename Derived>
33struct visitor_impl<Visitor, Derived, 1>
34{
35 static inline void run(const Derived &mat, Visitor& visitor)
36 {
37 return visitor.init(mat.coeff(0, 0), 0, 0);
38 }
39};
40
41template<typename Visitor, typename Derived>
42struct visitor_impl<Visitor, Derived, Dynamic>
43{
44 typedef typename Derived::Index Index;
45 static inline void run(const Derived& mat, Visitor& visitor)
46 {
47 visitor.init(mat.coeff(0,0), 0, 0);
48 for(Index i = 1; i < mat.rows(); ++i)
49 visitor(mat.coeff(i, 0), i, 0);
50 for(Index j = 1; j < mat.cols(); ++j)
51 for(Index i = 0; i < mat.rows(); ++i)
52 visitor(mat.coeff(i, j), i, j);
53 }
54};
55
56} // end namespace internal
57
58/** Applies the visitor \a visitor to the whole coefficients of the matrix or vector.
59 *
60 * The template parameter \a Visitor is the type of the visitor and provides the following interface:
61 * \code
62 * struct MyVisitor {
63 * // called for the first coefficient
64 * void init(const Scalar& value, Index i, Index j);
65 * // called for all other coefficients
66 * void operator() (const Scalar& value, Index i, Index j);
67 * };
68 * \endcode
69 *
70 * \note compared to one or two \em for \em loops, visitors offer automatic
71 * unrolling for small fixed size matrix.
72 *
73 * \sa minCoeff(Index*,Index*), maxCoeff(Index*,Index*), DenseBase::redux()
74 */
75template<typename Derived>
76template<typename Visitor>
77void DenseBase<Derived>::visit(Visitor& visitor) const
78{
79 enum { unroll = SizeAtCompileTime != Dynamic
80 && CoeffReadCost != Dynamic
81 && (SizeAtCompileTime == 1 || internal::functor_traits<Visitor>::Cost != Dynamic)
82 && SizeAtCompileTime * CoeffReadCost + (SizeAtCompileTime-1) * internal::functor_traits<Visitor>::Cost
83 <= EIGEN_UNROLLING_LIMIT };
84 return internal::visitor_impl<Visitor, Derived,
85 unroll ? int(SizeAtCompileTime) : Dynamic
86 >::run(derived(), visitor);
87}
88
89namespace internal {
90
91/** \internal
92 * \brief Base class to implement min and max visitors
93 */
94template <typename Derived>
95struct coeff_visitor
96{
97 typedef typename Derived::Index Index;
98 typedef typename Derived::Scalar Scalar;
99 Index row, col;
100 Scalar res;
101 inline void init(const Scalar& value, Index i, Index j)
102 {
103 res = value;
104 row = i;
105 col = j;
106 }
107};
108
109/** \internal
110 * \brief Visitor computing the min coefficient with its value and coordinates
111 *
112 * \sa DenseBase::minCoeff(Index*, Index*)
113 */
114template <typename Derived>
115struct min_coeff_visitor : coeff_visitor<Derived>
116{
117 typedef typename Derived::Index Index;
118 typedef typename Derived::Scalar Scalar;
119 void operator() (const Scalar& value, Index i, Index j)
120 {
121 if(value < this->res)
122 {
123 this->res = value;
124 this->row = i;
125 this->col = j;
126 }
127 }
128};
129
130template<typename Scalar>
131struct functor_traits<min_coeff_visitor<Scalar> > {
132 enum {
133 Cost = NumTraits<Scalar>::AddCost
134 };
135};
136
137/** \internal
138 * \brief Visitor computing the max coefficient with its value and coordinates
139 *
140 * \sa DenseBase::maxCoeff(Index*, Index*)
141 */
142template <typename Derived>
143struct max_coeff_visitor : coeff_visitor<Derived>
144{
145 typedef typename Derived::Index Index;
146 typedef typename Derived::Scalar Scalar;
147 void operator() (const Scalar& value, Index i, Index j)
148 {
149 if(value > this->res)
150 {
151 this->res = value;
152 this->row = i;
153 this->col = j;
154 }
155 }
156};
157
158template<typename Scalar>
159struct functor_traits<max_coeff_visitor<Scalar> > {
160 enum {
161 Cost = NumTraits<Scalar>::AddCost
162 };
163};
164
165} // end namespace internal
166
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700167/** \returns the minimum of all coefficients of *this and puts in *row and *col its location.
168 * \warning the result is undefined if \c *this contains NaN.
Narayan Kamathc981c482012-11-02 10:59:05 +0000169 *
170 * \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visitor(), DenseBase::minCoeff()
171 */
172template<typename Derived>
173template<typename IndexType>
174typename internal::traits<Derived>::Scalar
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700175DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
Narayan Kamathc981c482012-11-02 10:59:05 +0000176{
177 internal::min_coeff_visitor<Derived> minVisitor;
178 this->visit(minVisitor);
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700179 *rowId = minVisitor.row;
180 if (colId) *colId = minVisitor.col;
Narayan Kamathc981c482012-11-02 10:59:05 +0000181 return minVisitor.res;
182}
183
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700184/** \returns the minimum of all coefficients of *this and puts in *index its location.
185 * \warning the result is undefined if \c *this contains NaN.
Narayan Kamathc981c482012-11-02 10:59:05 +0000186 *
187 * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::minCoeff()
188 */
189template<typename Derived>
190template<typename IndexType>
191typename internal::traits<Derived>::Scalar
192DenseBase<Derived>::minCoeff(IndexType* index) const
193{
194 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
195 internal::min_coeff_visitor<Derived> minVisitor;
196 this->visit(minVisitor);
197 *index = (RowsAtCompileTime==1) ? minVisitor.col : minVisitor.row;
198 return minVisitor.res;
199}
200
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700201/** \returns the maximum of all coefficients of *this and puts in *row and *col its location.
202 * \warning the result is undefined if \c *this contains NaN.
Narayan Kamathc981c482012-11-02 10:59:05 +0000203 *
204 * \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
205 */
206template<typename Derived>
207template<typename IndexType>
208typename internal::traits<Derived>::Scalar
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700209DenseBase<Derived>::maxCoeff(IndexType* rowPtr, IndexType* colPtr) const
Narayan Kamathc981c482012-11-02 10:59:05 +0000210{
211 internal::max_coeff_visitor<Derived> maxVisitor;
212 this->visit(maxVisitor);
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700213 *rowPtr = maxVisitor.row;
214 if (colPtr) *colPtr = maxVisitor.col;
Narayan Kamathc981c482012-11-02 10:59:05 +0000215 return maxVisitor.res;
216}
217
Carlos Hernandez7faaa9f2014-08-05 17:53:32 -0700218/** \returns the maximum of all coefficients of *this and puts in *index its location.
219 * \warning the result is undefined if \c *this contains NaN.
Narayan Kamathc981c482012-11-02 10:59:05 +0000220 *
221 * \sa DenseBase::maxCoeff(IndexType*,IndexType*), DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visitor(), DenseBase::maxCoeff()
222 */
223template<typename Derived>
224template<typename IndexType>
225typename internal::traits<Derived>::Scalar
226DenseBase<Derived>::maxCoeff(IndexType* index) const
227{
228 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
229 internal::max_coeff_visitor<Derived> maxVisitor;
230 this->visit(maxVisitor);
231 *index = (RowsAtCompileTime==1) ? maxVisitor.col : maxVisitor.row;
232 return maxVisitor.res;
233}
234
235} // end namespace Eigen
236
237#endif // EIGEN_VISITOR_H