10#ifndef EIGEN_FIND_COEFF_H
11#define EIGEN_FIND_COEFF_H
14#include "./InternalHeaderCheck.h"
20template <typename Scalar, int NaNPropagation, bool IsInteger = NumTraits<Scalar>::IsInteger>
21struct max_coeff_functor {
22 EIGEN_DEVICE_FUNC
inline bool compareCoeff(
const Scalar& incumbent,
const Scalar& candidate)
const {
23 return candidate > incumbent;
25 template <
typename Packet>
26 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate)
const {
27 return pcmp_lt(incumbent, candidate);
29 template <
typename Packet>
30 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
35template <
typename Scalar>
37 EIGEN_DEVICE_FUNC
inline Scalar compareCoeff(
const Scalar& incumbent,
const Scalar& candidate) {
38 return (candidate > incumbent) || ((candidate != candidate) && (incumbent == incumbent));
40 template <
typename Packet>
41 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate) {
42 return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(incumbent));
44 template <
typename Packet>
45 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
46 return predux_max<PropagateNaN>(a);
50template <
typename Scalar>
52 EIGEN_DEVICE_FUNC
inline bool compareCoeff(
const Scalar& incumbent,
const Scalar& candidate)
const {
53 return (candidate > incumbent) || ((candidate == candidate) && (incumbent != incumbent));
55 template <
typename Packet>
56 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate)
const {
57 return pandnot(pcmp_lt_or_nan(incumbent, candidate), pisnan(candidate));
59 template <
typename Packet>
60 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
61 return predux_max<PropagateNumbers>(a);
65template <typename Scalar, int NaNPropagation, bool IsInteger = NumTraits<Scalar>::IsInteger>
66struct min_coeff_functor {
67 EIGEN_DEVICE_FUNC
inline bool compareCoeff(
const Scalar& incumbent,
const Scalar& candidate)
const {
68 return candidate < incumbent;
70 template <
typename Packet>
71 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate)
const {
72 return pcmp_lt(candidate, incumbent);
74 template <
typename Packet>
75 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
80template <
typename Scalar>
82 EIGEN_DEVICE_FUNC
inline Scalar compareCoeff(
const Scalar& incumbent,
const Scalar& candidate) {
83 return (candidate < incumbent) || ((candidate != candidate) && (incumbent == incumbent));
85 template <
typename Packet>
86 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate) {
87 return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(incumbent));
89 template <
typename Packet>
90 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
91 return predux_min<PropagateNaN>(a);
95template <
typename Scalar>
97 EIGEN_DEVICE_FUNC
inline bool compareCoeff(
const Scalar& incumbent,
const Scalar& candidate)
const {
98 return (candidate < incumbent) || ((candidate == candidate) && (incumbent != incumbent));
100 template <
typename Packet>
101 EIGEN_DEVICE_FUNC
inline Packet comparePacket(
const Packet& incumbent,
const Packet& candidate)
const {
102 return pandnot(pcmp_lt_or_nan(candidate, incumbent), pisnan(candidate));
104 template <
typename Packet>
105 EIGEN_DEVICE_FUNC
inline Scalar predux(
const Packet& a)
const {
106 return predux_min<PropagateNumbers>(a);
110template <
typename Scalar>
111struct min_max_traits {
112 static constexpr bool PacketAccess = packet_traits<Scalar>::Vectorizable;
114template <
typename Scalar,
int NaNPropagation>
115struct functor_traits<max_coeff_functor<Scalar, NaNPropagation>> : min_max_traits<Scalar> {};
116template <
typename Scalar,
int NaNPropagation>
117struct functor_traits<min_coeff_functor<Scalar, NaNPropagation>> : min_max_traits<Scalar> {};
119template <
typename Evaluator,
typename Func,
bool Linear,
bool Vectorize>
120struct find_coeff_loop;
121template <
typename Evaluator,
typename Func>
122struct find_coeff_loop<Evaluator, Func, false, false> {
123 using Scalar =
typename Evaluator::Scalar;
124 static EIGEN_DEVICE_FUNC
inline void run(
const Evaluator& eval, Func& func, Scalar& res,
Index& outer,
Index& inner) {
125 Index outerSize = eval.outerSize();
126 Index innerSize = eval.innerSize();
133 for (
Index j = 0; j < outerSize; j++) {
134 for (
Index i = 0; i < innerSize; i++) {
135 Scalar xprCoeff = eval.coeffByOuterInner(j, i);
136 bool newRes = func.compareCoeff(res, xprCoeff);
146template <
typename Evaluator,
typename Func>
147struct find_coeff_loop<Evaluator, Func, true, false> {
148 using Scalar =
typename Evaluator::Scalar;
149 static EIGEN_DEVICE_FUNC
inline void run(
const Evaluator& eval, Func& func, Scalar& res,
Index& index) {
150 Index size = eval.size();
156 for (
Index k = 0; k < size; k++) {
157 Scalar xprCoeff = eval.coeff(k);
158 bool newRes = func.compareCoeff(res, xprCoeff);
166template <
typename Evaluator,
typename Func>
167struct find_coeff_loop<Evaluator, Func, false, true> {
168 using ScalarImpl = find_coeff_loop<Evaluator, Func, false, false>;
169 using Scalar =
typename Evaluator::Scalar;
170 using Packet =
typename Evaluator::Packet;
171 static constexpr int PacketSize = unpacket_traits<Packet>::size;
172 static EIGEN_DEVICE_FUNC
inline void run(
const Evaluator& eval, Func& func, Scalar& result,
Index& outer,
174 Index outerSize = eval.outerSize();
175 Index innerSize = eval.innerSize();
176 Index packetEnd = numext::round_down(innerSize, PacketSize);
183 bool checkPacket =
false;
185 for (
Index j = 0; j < outerSize; j++) {
186 Packet resultPacket = pset1<Packet>(result);
187 for (
Index i = 0; i < packetEnd; i += PacketSize) {
188 Packet xprPacket = eval.template packetByOuterInner<Unaligned, Packet>(j, i);
189 if (predux_any(func.comparePacket(resultPacket, xprPacket))) {
192 result = func.predux(xprPacket);
193 resultPacket = pset1<Packet>(result);
198 for (
Index i = packetEnd; i < innerSize; i++) {
199 Scalar xprCoeff = eval.coeffByOuterInner(j, i);
200 if (func.compareCoeff(result, xprCoeff)) {
210 result = eval.coeffByOuterInner(outer, inner);
211 Index i_end = inner + PacketSize;
212 for (
Index i = inner; i < i_end; i++) {
213 Scalar xprCoeff = eval.coeffByOuterInner(outer, i);
214 if (func.compareCoeff(result, xprCoeff)) {
222template <
typename Evaluator,
typename Func>
223struct find_coeff_loop<Evaluator, Func, true, true> {
224 using ScalarImpl = find_coeff_loop<Evaluator, Func, true, false>;
225 using Scalar =
typename Evaluator::Scalar;
226 using Packet =
typename Evaluator::Packet;
227 static constexpr int PacketSize = unpacket_traits<Packet>::size;
228 static constexpr int Alignment = Evaluator::Alignment;
230 static EIGEN_DEVICE_FUNC
inline void run(
const Evaluator& eval, Func& func, Scalar& result,
Index& index) {
231 Index size = eval.size();
232 Index packetEnd = numext::round_down(size, PacketSize);
238 Packet resultPacket = pset1<Packet>(result);
239 bool checkPacket =
false;
241 for (
Index k = 0; k < packetEnd; k += PacketSize) {
242 Packet xprPacket = eval.template packet<Alignment, Packet>(k);
243 if (predux_any(func.comparePacket(resultPacket, xprPacket))) {
245 result = func.predux(xprPacket);
246 resultPacket = pset1<Packet>(result);
251 for (
Index k = packetEnd; k < size; k++) {
252 Scalar xprCoeff = eval.coeff(k);
253 if (func.compareCoeff(result, xprCoeff)) {
261 result = eval.coeff(index);
262 Index k_end = index + PacketSize;
263 for (
Index k = index; k < k_end; k++) {
264 Scalar xprCoeff = eval.coeff(k);
265 if (func.compareCoeff(result, xprCoeff)) {
274template <
typename Derived>
275struct find_coeff_evaluator :
public evaluator<Derived> {
276 using Base = evaluator<Derived>;
277 using Scalar =
typename Derived::Scalar;
278 using Packet =
typename packet_traits<Scalar>::type;
279 static constexpr int Flags = Base::Flags;
280 static constexpr bool IsRowMajor = bool(Flags &
RowMajorBit);
281 EIGEN_DEVICE_FUNC
inline find_coeff_evaluator(
const Derived& xpr) : Base(xpr), m_xpr(xpr) {}
283 EIGEN_DEVICE_FUNC
inline Scalar coeffByOuterInner(
Index outer,
Index inner)
const {
284 Index row = IsRowMajor ? outer : inner;
285 Index col = IsRowMajor ? inner : outer;
286 return Base::coeff(row, col);
288 template <
int LoadMode,
typename PacketType>
289 EIGEN_DEVICE_FUNC
inline PacketType packetByOuterInner(
Index outer,
Index inner)
const {
290 Index row = IsRowMajor ? outer : inner;
291 Index col = IsRowMajor ? inner : outer;
292 return Base::template packet<LoadMode, PacketType>(row, col);
295 EIGEN_DEVICE_FUNC
inline Index innerSize()
const {
return m_xpr.innerSize(); }
296 EIGEN_DEVICE_FUNC
inline Index outerSize()
const {
return m_xpr.outerSize(); }
297 EIGEN_DEVICE_FUNC
inline Index size()
const {
return m_xpr.size(); }
299 const Derived& m_xpr;
302template <
typename Derived,
typename Func>
303struct find_coeff_impl {
304 using Evaluator = find_coeff_evaluator<Derived>;
305 static constexpr int Flags = Evaluator::Flags;
306 static constexpr int Alignment = Evaluator::Alignment;
307 static constexpr bool IsRowMajor = Derived::IsRowMajor;
308 static constexpr int MaxInnerSizeAtCompileTime =
309 IsRowMajor ? Derived::MaxColsAtCompileTime : Derived::MaxRowsAtCompileTime;
310 static constexpr int MaxSizeAtCompileTime = Derived::MaxSizeAtCompileTime;
312 using Scalar =
typename Derived::Scalar;
313 using Packet =
typename Evaluator::Packet;
315 static constexpr int PacketSize = unpacket_traits<Packet>::size;
317 static constexpr bool DontVectorize =
318 enum_lt_not_dynamic(Linearize ? MaxSizeAtCompileTime : MaxInnerSizeAtCompileTime, PacketSize);
319 static constexpr bool Vectorize =
320 !DontVectorize && bool(Flags &
PacketAccessBit) && functor_traits<Func>::PacketAccess;
322 using Loop = find_coeff_loop<Evaluator, Func, Linearize, Vectorize>;
324 template <
bool ForwardLinearAccess = Linearize, std::enable_if_t<!ForwardLinearAccess,
bool> = true>
325 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(
const Derived& xpr, Func& func, Scalar& res,
Index& outer,
328 Loop::run(eval, func, res, outer, inner);
330 template <
bool ForwardLinearAccess = Linearize, std::enable_if_t<ForwardLinearAccess,
bool> = true>
331 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(
const Derived& xpr, Func& func, Scalar& res,
Index& outer,
335 run(xpr, func, res, index);
336 outer = index / xpr.innerSize();
337 inner = index % xpr.innerSize();
339 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void run(
const Derived& xpr, Func& func, Scalar& res,
Index& index) {
341 Loop::run(eval, func, res, index);
345template <
typename Derived,
typename IndexType,
typename Func>
346EIGEN_DEVICE_FUNC
typename internal::traits<Derived>::Scalar findCoeff(
const DenseBase<Derived>& mat, Func& func,
347 IndexType* rowPtr, IndexType* colPtr) {
348 eigen_assert(mat.rows() > 0 && mat.cols() > 0 &&
"you are using an empty matrix");
350 using FindCoeffImpl = internal::find_coeff_impl<Derived, Func>;
353 Scalar res = mat.coeff(0, 0);
354 FindCoeffImpl::run(mat.derived(), func, res, outer, inner);
355 *rowPtr = internal::convert_index<IndexType>(Derived::IsRowMajor ? outer : inner);
356 if (colPtr) *colPtr = internal::convert_index<IndexType>(Derived::IsRowMajor ? inner : outer);
360template <
typename Derived,
typename IndexType,
typename Func>
361EIGEN_DEVICE_FUNC
typename internal::traits<Derived>::Scalar findCoeff(
const DenseBase<Derived>& mat, Func& func,
362 IndexType* indexPtr) {
363 eigen_assert(mat.size() > 0 &&
"you are using an empty matrix");
364 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
366 using FindCoeffImpl = internal::find_coeff_impl<Derived, Func>;
368 Scalar res = mat.coeff(0);
369 FindCoeffImpl::run(mat.derived(), func, res, index);
370 *indexPtr = internal::convert_index<IndexType>(index);
389template <
typename Derived>
390template <
int NaNPropagation,
typename IndexType>
392 IndexType* colPtr)
const {
393 using Func = internal::min_coeff_functor<Scalar, NaNPropagation>;
395 return internal::findCoeff(derived(), func, rowPtr, colPtr);
411template <
typename Derived>
412template <
int NaNPropagation,
typename IndexType>
414 using Func = internal::min_coeff_functor<Scalar, NaNPropagation>;
416 return internal::findCoeff(derived(), func, indexPtr);
432template <
typename Derived>
433template <
int NaNPropagation,
typename IndexType>
435 IndexType* colPtr)
const {
436 using Func = internal::max_coeff_functor<Scalar, NaNPropagation>;
438 return internal::findCoeff(derived(), func, rowPtr, colPtr);
454template <
typename Derived>
455template <
int NaNPropagation,
typename IndexType>
457 using Func = internal::max_coeff_functor<Scalar, NaNPropagation>;
459 return internal::findCoeff(derived(), func, indexPtr);
internal::traits< Derived >::Scalar minCoeff() const
Definition Redux.h:464
internal::traits< Derived >::Scalar Scalar
Definition DenseBase.h:62
internal::traits< Derived >::Scalar maxCoeff() const
Definition Redux.h:477
@ PropagateNaN
Definition Constants.h:342
@ PropagateNumbers
Definition Constants.h:344
const unsigned int PacketAccessBit
Definition Constants.h:97
const unsigned int LinearAccessBit
Definition Constants.h:133
const unsigned int RowMajorBit
Definition Constants.h:70
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82