15#include "./InternalHeaderCheck.h"
29template <
typename Func,
typename Evaluator>
32 typedef typename find_best_packet<typename Evaluator::Scalar, Evaluator::SizeAtCompileTime>::type PacketType;
34 PacketSize = unpacket_traits<PacketType>::size,
35 InnerMaxSize = int(Evaluator::IsRowMajor) ? Evaluator::MaxColsAtCompileTime : Evaluator::MaxRowsAtCompileTime,
36 OuterMaxSize = int(Evaluator::IsRowMajor) ? Evaluator::MaxRowsAtCompileTime : Evaluator::MaxColsAtCompileTime,
38 : int(OuterMaxSize) ==
Dynamic ? (int(InnerMaxSize) >= int(PacketSize) ?
Dynamic : 0)
39 : (int(InnerMaxSize) / int(PacketSize)) * int(OuterMaxSize)
44 MightVectorize = (
int(Evaluator::Flags) &
ActualPacketAccessBit) && (functor_traits<Func>::PacketAccess),
45 MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize),
46 MaySliceVectorize = bool(MightVectorize) && (int(SliceVectorizedWork) ==
Dynamic || int(SliceVectorizedWork) >= 3)
51 Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
52 : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
53 : int(MayLinearize) ? int(LinearTraversal)
54 : int(DefaultTraversal)
59 Cost = Evaluator::SizeAtCompileTime ==
Dynamic
61 : int(Evaluator::SizeAtCompileTime) * int(Evaluator::CoeffReadCost) +
62 (Evaluator::SizeAtCompileTime - 1) * functor_traits<Func>::Cost,
63 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (
int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize))
67 enum { Unrolling = Cost <= UnrollingLimit ? CompleteUnrolling : NoUnrolling };
69#ifdef EIGEN_DEBUG_ASSIGN
71 std::cerr <<
"Xpr: " <<
typeid(
typename Evaluator::XprType).name() << std::endl;
72 std::cerr.setf(std::ios::hex, std::ios::basefield);
73 EIGEN_DEBUG_VAR(Evaluator::Flags)
74 std::cerr.unsetf(std::ios::hex);
75 EIGEN_DEBUG_VAR(InnerMaxSize)
76 EIGEN_DEBUG_VAR(OuterMaxSize)
77 EIGEN_DEBUG_VAR(SliceVectorizedWork)
78 EIGEN_DEBUG_VAR(PacketSize)
79 EIGEN_DEBUG_VAR(MightVectorize)
80 EIGEN_DEBUG_VAR(MayLinearVectorize)
81 EIGEN_DEBUG_VAR(MaySliceVectorize)
82 std::cerr <<
"Traversal"
83 <<
" = " << Traversal <<
" (" << demangle_traversal(Traversal) <<
")" << std::endl;
84 EIGEN_DEBUG_VAR(UnrollingLimit)
85 std::cerr <<
"Unrolling"
86 <<
" = " << Unrolling <<
" (" << demangle_unrolling(Unrolling) <<
")" << std::endl;
87 std::cerr << std::endl;
98template <
typename Func,
typename Evaluator, Index Start, Index Length>
99struct redux_novec_unroller {
100 static constexpr Index HalfLength = Length / 2;
102 typedef typename Evaluator::Scalar Scalar;
104 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func) {
105 return func(redux_novec_unroller<Func, Evaluator, Start, HalfLength>::run(eval, func),
106 redux_novec_unroller<Func, Evaluator, Start + HalfLength, Length - HalfLength>::run(eval, func));
110template <
typename Func,
typename Evaluator, Index Start>
111struct redux_novec_unroller<Func, Evaluator, Start, 1> {
112 static constexpr Index outer = Start / Evaluator::InnerSizeAtCompileTime;
113 static constexpr Index inner = Start % Evaluator::InnerSizeAtCompileTime;
115 typedef typename Evaluator::Scalar Scalar;
117 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func&) {
118 return eval.coeffByOuterInner(outer, inner);
125template <
typename Func,
typename Evaluator, Index Start>
126struct redux_novec_unroller<Func, Evaluator, Start, 0> {
127 typedef typename Evaluator::Scalar Scalar;
128 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator&,
const Func&) {
return Scalar(); }
131template <
typename Func,
typename Evaluator, Index Start, Index Length>
132struct redux_novec_linear_unroller {
133 static constexpr Index HalfLength = Length / 2;
135 typedef typename Evaluator::Scalar Scalar;
137 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func) {
138 return func(redux_novec_linear_unroller<Func, Evaluator, Start, HalfLength>::run(eval, func),
139 redux_novec_linear_unroller<Func, Evaluator, Start + HalfLength, Length - HalfLength>::run(eval, func));
143template <
typename Func,
typename Evaluator, Index Start>
144struct redux_novec_linear_unroller<Func, Evaluator, Start, 1> {
145 typedef typename Evaluator::Scalar Scalar;
147 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func&) {
148 return eval.coeff(Start);
155template <
typename Func,
typename Evaluator, Index Start>
156struct redux_novec_linear_unroller<Func, Evaluator, Start, 0> {
157 typedef typename Evaluator::Scalar Scalar;
158 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator&,
const Func&) {
return Scalar(); }
163template <
typename Func,
typename Evaluator, Index Start, Index Length>
164struct redux_vec_unroller {
165 template <
typename PacketType>
166 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE PacketType run(
const Evaluator& eval,
const Func& func) {
167 constexpr Index HalfLength = Length / 2;
169 return func.packetOp(
170 redux_vec_unroller<Func, Evaluator, Start, HalfLength>::template run<PacketType>(eval, func),
171 redux_vec_unroller<Func, Evaluator, Start + HalfLength, Length - HalfLength>::template run<PacketType>(eval,
176template <
typename Func,
typename Evaluator, Index Start>
177struct redux_vec_unroller<Func, Evaluator, Start, 1> {
178 template <
typename PacketType>
179 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE PacketType run(
const Evaluator& eval,
const Func&) {
180 constexpr Index PacketSize = unpacket_traits<PacketType>::size;
181 constexpr Index index = Start * PacketSize;
182 constexpr Index outer = index / int(Evaluator::InnerSizeAtCompileTime);
183 constexpr Index inner = index % int(Evaluator::InnerSizeAtCompileTime);
184 constexpr int alignment = Evaluator::Alignment;
186 return eval.template packetByOuterInner<alignment, PacketType>(outer, inner);
190template <
typename Func,
typename Evaluator, Index Start, Index Length>
191struct redux_vec_linear_unroller {
192 template <
typename PacketType>
193 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE PacketType run(
const Evaluator& eval,
const Func& func) {
194 constexpr Index HalfLength = Length / 2;
196 return func.packetOp(
197 redux_vec_linear_unroller<Func, Evaluator, Start, HalfLength>::template run<PacketType>(eval, func),
198 redux_vec_linear_unroller<Func, Evaluator, Start + HalfLength, Length - HalfLength>::template run<PacketType>(
203template <
typename Func,
typename Evaluator, Index Start>
204struct redux_vec_linear_unroller<Func, Evaluator, Start, 1> {
205 template <
typename PacketType>
206 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE PacketType run(
const Evaluator& eval,
const Func&) {
207 constexpr Index PacketSize = unpacket_traits<PacketType>::size;
208 constexpr Index index = (Start * PacketSize);
209 constexpr int alignment = Evaluator::Alignment;
210 return eval.template packet<alignment, PacketType>(index);
218template <typename Func, typename Evaluator, int Traversal = redux_traits<Func, Evaluator>::Traversal,
219 int Unrolling = redux_traits<Func, Evaluator>::Unrolling>
222template <
typename Func,
typename Evaluator>
223struct redux_impl<Func, Evaluator, DefaultTraversal, NoUnrolling> {
224 typedef typename Evaluator::Scalar Scalar;
226 template <
typename XprType>
227 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func,
const XprType& xpr) {
228 eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 &&
"you are using an empty matrix");
229 Scalar res = eval.coeffByOuterInner(0, 0);
230 for (Index i = 1; i < xpr.innerSize(); ++i) res = func(res, eval.coeffByOuterInner(0, i));
231 for (Index i = 1; i < xpr.outerSize(); ++i)
232 for (Index j = 0; j < xpr.innerSize(); ++j) res = func(res, eval.coeffByOuterInner(i, j));
237template <
typename Func,
typename Evaluator>
238struct redux_impl<Func, Evaluator, LinearTraversal, NoUnrolling> {
239 typedef typename Evaluator::Scalar Scalar;
241 template <
typename XprType>
242 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func,
const XprType& xpr) {
243 eigen_assert(xpr.size() > 0 &&
"you are using an empty matrix");
244 Scalar res = eval.coeff(0);
245 for (Index k = 1; k < xpr.size(); ++k) res = func(res, eval.coeff(k));
250template <
typename Func,
typename Evaluator>
251struct redux_impl<Func, Evaluator, DefaultTraversal, CompleteUnrolling>
252 : redux_novec_unroller<Func, Evaluator, 0, Evaluator::SizeAtCompileTime> {
253 typedef redux_novec_unroller<Func, Evaluator, 0, Evaluator::SizeAtCompileTime> Base;
254 typedef typename Evaluator::Scalar Scalar;
255 template <
typename XprType>
256 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func,
258 return Base::run(eval, func);
262template <
typename Func,
typename Evaluator>
263struct redux_impl<Func, Evaluator, LinearTraversal, CompleteUnrolling>
264 : redux_novec_linear_unroller<Func, Evaluator, 0, Evaluator::SizeAtCompileTime> {
265 typedef redux_novec_linear_unroller<Func, Evaluator, 0, Evaluator::SizeAtCompileTime> Base;
266 typedef typename Evaluator::Scalar Scalar;
267 template <
typename XprType>
268 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func,
270 return Base::run(eval, func);
274template <
typename Func,
typename Evaluator>
275struct redux_impl<Func, Evaluator, LinearVectorizedTraversal, NoUnrolling> {
276 typedef typename Evaluator::Scalar Scalar;
277 typedef typename redux_traits<Func, Evaluator>::PacketType PacketScalar;
279 template <
typename XprType>
280 static Scalar run(
const Evaluator& eval,
const Func& func,
const XprType& xpr) {
281 const Index size = xpr.size();
283 constexpr Index packetSize = redux_traits<Func, Evaluator>::PacketSize;
284 constexpr int packetAlignment = unpacket_traits<PacketScalar>::alignment;
285 constexpr int alignment0 =
286 (bool(Evaluator::Flags & DirectAccessBit) && bool(packet_traits<Scalar>::AlignedOnScalar))
287 ?
int(packetAlignment)
289 constexpr int alignment = plain_enum_max(alignment0, Evaluator::Alignment);
290 const Index alignedStart = internal::first_default_aligned(xpr);
291 const Index alignedSize2 = ((size - alignedStart) / (2 * packetSize)) * (2 * packetSize);
292 const Index alignedSize = ((size - alignedStart) / (packetSize)) * (packetSize);
293 const Index alignedEnd2 = alignedStart + alignedSize2;
294 const Index alignedEnd = alignedStart + alignedSize;
297 PacketScalar packet_res0 = eval.template packet<alignment, PacketScalar>(alignedStart);
298 if (alignedSize > packetSize)
300 PacketScalar packet_res1 = eval.template packet<alignment, PacketScalar>(alignedStart + packetSize);
301 for (Index index = alignedStart + 2 * packetSize; index < alignedEnd2; index += 2 * packetSize) {
302 packet_res0 = func.packetOp(packet_res0, eval.template packet<alignment, PacketScalar>(index));
303 packet_res1 = func.packetOp(packet_res1, eval.template packet<alignment, PacketScalar>(index + packetSize));
306 packet_res0 = func.packetOp(packet_res0, packet_res1);
307 if (alignedEnd > alignedEnd2)
308 packet_res0 = func.packetOp(packet_res0, eval.template packet<alignment, PacketScalar>(alignedEnd2));
310 res = func.predux(packet_res0);
312 for (
Index index = 0; index < alignedStart; ++index) res = func(res, eval.coeff(index));
314 for (
Index index = alignedEnd; index < size; ++index) res = func(res, eval.coeff(index));
319 for (
Index index = 1; index < size; ++index) res = func(res, eval.coeff(index));
327template <
typename Func,
typename Evaluator,
int Unrolling>
328struct redux_impl<Func, Evaluator, SliceVectorizedTraversal, Unrolling> {
329 typedef typename Evaluator::Scalar Scalar;
330 typedef typename redux_traits<Func, Evaluator>::PacketType PacketType;
332 template <
typename XprType>
333 EIGEN_DEVICE_FUNC
static Scalar run(
const Evaluator& eval,
const Func& func,
const XprType& xpr) {
334 eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 &&
"you are using an empty matrix");
335 constexpr Index packetSize = redux_traits<Func, Evaluator>::PacketSize;
336 const Index innerSize = xpr.innerSize();
337 const Index outerSize = xpr.outerSize();
338 const Index packetedInnerSize = ((innerSize) / packetSize) * packetSize;
340 if (packetedInnerSize) {
341 PacketType packet_res = eval.template packet<Unaligned, PacketType>(0, 0);
342 for (Index j = 0; j < outerSize; ++j)
343 for (Index i = (j == 0 ? packetSize : 0); i < packetedInnerSize; i += Index(packetSize))
344 packet_res = func.packetOp(packet_res, eval.template packetByOuterInner<Unaligned, PacketType>(j, i));
346 res = func.predux(packet_res);
347 for (Index j = 0; j < outerSize; ++j)
348 for (Index i = packetedInnerSize; i < innerSize; ++i) res = func(res, eval.coeffByOuterInner(j, i));
352 res = redux_impl<Func, Evaluator, DefaultTraversal, NoUnrolling>::run(eval, func, xpr);
359template <
typename Func,
typename Evaluator>
360struct redux_impl<Func, Evaluator, LinearVectorizedTraversal, CompleteUnrolling> {
361 typedef typename Evaluator::Scalar Scalar;
363 typedef typename redux_traits<Func, Evaluator>::PacketType PacketType;
364 static constexpr Index PacketSize = redux_traits<Func, Evaluator>::PacketSize;
365 static constexpr Index Size = Evaluator::SizeAtCompileTime;
366 static constexpr Index VectorizedSize = (int(Size) / int(PacketSize)) *
int(PacketSize);
368 template <
typename XprType>
369 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Evaluator& eval,
const Func& func,
const XprType& xpr) {
370 EIGEN_ONLY_USED_FOR_DEBUG(xpr)
371 eigen_assert(xpr.rows() > 0 && xpr.cols() > 0 &&
"you are using an empty matrix");
372 if (VectorizedSize > 0) {
373 Scalar res = func.predux(
374 redux_vec_linear_unroller<Func, Evaluator, 0, Size / PacketSize>::template run<PacketType>(eval, func));
375 if (VectorizedSize != Size)
377 res, redux_novec_linear_unroller<Func, Evaluator, VectorizedSize, Size - VectorizedSize>::run(eval, func));
380 return redux_novec_linear_unroller<Func, Evaluator, 0, Size>::run(eval, func);
386template <
typename XprType_>
387class redux_evaluator :
public internal::evaluator<XprType_> {
388 typedef internal::evaluator<XprType_> Base;
391 typedef XprType_ XprType;
392 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit redux_evaluator(
const XprType& xpr) : Base(xpr) {}
394 typedef typename XprType::Scalar Scalar;
395 typedef typename XprType::CoeffReturnType CoeffReturnType;
396 typedef typename XprType::PacketScalar PacketScalar;
399 MaxRowsAtCompileTime = XprType::MaxRowsAtCompileTime,
400 MaxColsAtCompileTime = XprType::MaxColsAtCompileTime,
403 Flags = Base::Flags & ~DirectAccessBit,
404 IsRowMajor = XprType::IsRowMajor,
405 SizeAtCompileTime = XprType::SizeAtCompileTime,
406 InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime
409 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner)
const {
410 return Base::coeff(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer);
413 template <
int LoadMode,
typename PacketType>
414 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetByOuterInner(
Index outer,
Index inner)
const {
415 return Base::template packet<LoadMode, PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer);
434template <
typename Derived>
435template <
typename Func>
437 const Func& func)
const {
438 eigen_assert(this->rows() > 0 && this->cols() > 0 &&
"you are using an empty matrix");
440 typedef typename internal::redux_evaluator<Derived> ThisEvaluator;
441 ThisEvaluator thisEval(derived());
445 return internal::redux_impl<Func, ThisEvaluator>::run(thisEval, func, derived());
455template <
typename Derived>
456template <
int NaNPropagation>
458 return derived().redux(Eigen::internal::scalar_min_op<Scalar, Scalar, NaNPropagation>());
468template <
typename Derived>
469template <
int NaNPropagation>
471 return derived().redux(Eigen::internal::scalar_max_op<Scalar, Scalar, NaNPropagation>());
480template <
typename Derived>
482 if (SizeAtCompileTime == 0 || (SizeAtCompileTime ==
Dynamic && size() == 0))
return Scalar(0);
483 return derived().redux(Eigen::internal::scalar_sum_op<Scalar, Scalar>());
490template <
typename Derived>
492#ifdef __INTEL_COMPILER
494#pragma warning(disable : 2259)
496 return Scalar(derived().redux(Eigen::internal::scalar_sum_op<Scalar, Scalar>())) /
Scalar(this->size());
497#ifdef __INTEL_COMPILER
509template <
typename Derived>
511 if (SizeAtCompileTime == 0 || (SizeAtCompileTime ==
Dynamic && size() == 0))
return Scalar(1);
512 return derived().redux(Eigen::internal::scalar_product_op<Scalar>());
521template <
typename Derived>
523 return derived().diagonal().sum();
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:44
internal::traits< Derived >::Scalar minCoeff() const
Definition Redux.h:457
Scalar mean() const
Definition Redux.h:491
internal::traits< Derived >::Scalar Scalar
Definition DenseBase.h:62
internal::traits< Derived >::Scalar maxCoeff() const
Definition Redux.h:470
Scalar sum() const
Definition Redux.h:481
Scalar prod() const
Definition Redux.h:510
Scalar trace() const
Definition Redux.h:522
const unsigned int ActualPacketAccessBit
Definition Constants.h:108
const unsigned int LinearAccessBit
Definition Constants.h:133
Namespace containing all symbols from the Eigen library.
Definition Core:137
const int HugeCost
Definition Constants.h:48
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:83
const int Dynamic
Definition Constants.h:25