26 template<
typename Func,
typename Derived>
31 PacketSize = packet_traits<typename Derived::Scalar>::size,
32 InnerMaxSize = int(Derived::IsRowMajor)
33 ? Derived::MaxColsAtCompileTime
34 : Derived::MaxRowsAtCompileTime
39 && (functor_traits<Func>::PacketAccess),
40 MayLinearVectorize = MightVectorize && (int(Derived::Flags)&
LinearAccessBit),
41 MaySliceVectorize = MightVectorize &&
int(InnerMaxSize)>=3*PacketSize
46 Traversal = int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
47 : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
48 : int(DefaultTraversal)
53 Cost = ( Derived::SizeAtCompileTime == Dynamic
54 || Derived::CoeffReadCost == Dynamic
55 || (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost == Dynamic)
57 : Derived::SizeAtCompileTime * Derived::CoeffReadCost
58 + (Derived::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
59 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (
int(Traversal) == int(DefaultTraversal) ? 1 : int(PacketSize))
64 Unrolling = Cost != Dynamic && Cost <= UnrollingLimit
69 #ifdef EIGEN_DEBUG_ASSIGN
72 std::cerr <<
"Xpr: " <<
typeid(
typename Derived::XprType).name() << std::endl;
73 std::cerr.setf(std::ios::hex, std::ios::basefield);
74 EIGEN_DEBUG_VAR(Derived::Flags)
75 std::cerr.unsetf(
std::ios::hex);
76 EIGEN_DEBUG_VAR(InnerMaxSize)
77 EIGEN_DEBUG_VAR(PacketSize)
78 EIGEN_DEBUG_VAR(MightVectorize)
79 EIGEN_DEBUG_VAR(MayLinearVectorize)
80 EIGEN_DEBUG_VAR(MaySliceVectorize)
81 EIGEN_DEBUG_VAR(Traversal)
82 EIGEN_DEBUG_VAR(UnrollingLimit)
83 EIGEN_DEBUG_VAR(Unrolling)
95 template<
typename Func,
typename Derived,
int Start,
int Length>
96 struct redux_novec_unroller
102 typedef typename Derived::Scalar Scalar;
105 static EIGEN_STRONG_INLINE Scalar run(
const Derived &mat,
const Func& func)
107 return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
108 redux_novec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func));
112 template<
typename Func,
typename Derived,
int Start>
113 struct redux_novec_unroller<Func, Derived, Start, 1>
116 outer = Start / Derived::InnerSizeAtCompileTime,
117 inner = Start % Derived::InnerSizeAtCompileTime
120 typedef typename Derived::Scalar Scalar;
123 static EIGEN_STRONG_INLINE Scalar run(
const Derived &mat,
const Func&)
125 return mat.coeffByOuterInner(outer, inner);
132 template<
typename Func,
typename Derived,
int Start>
133 struct redux_novec_unroller<Func, Derived, Start, 0>
135 typedef typename Derived::Scalar Scalar;
137 static EIGEN_STRONG_INLINE Scalar run(
const Derived&,
const Func&) {
return Scalar(); }
142 template<
typename Func,
typename Derived,
int Start,
int Length>
143 struct redux_vec_unroller
146 PacketSize = packet_traits<typename Derived::Scalar>::size,
147 HalfLength = Length/2
150 typedef typename Derived::Scalar Scalar;
151 typedef typename packet_traits<Scalar>::type PacketScalar;
153 static EIGEN_STRONG_INLINE PacketScalar run(
const Derived &mat,
const Func& func)
155 return func.packetOp(
156 redux_vec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
157 redux_vec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func) );
161 template<
typename Func,
typename Derived,
int Start>
162 struct redux_vec_unroller<Func, Derived, Start, 1>
165 index = Start * packet_traits<typename Derived::Scalar>::size,
166 outer = index / int(Derived::InnerSizeAtCompileTime),
167 inner = index % int(Derived::InnerSizeAtCompileTime),
168 alignment = Derived::Alignment
171 typedef typename Derived::Scalar Scalar;
172 typedef typename packet_traits<Scalar>::type PacketScalar;
174 static EIGEN_STRONG_INLINE PacketScalar run(
const Derived &mat,
const Func&)
176 return mat.template packetByOuterInner<alignment,PacketScalar>(outer, inner);
184 template<
typename Func,
typename Derived,
185 int Traversal = redux_traits<Func, Derived>::Traversal,
186 int Unrolling = redux_traits<Func, Derived>::Unrolling
190 template<
typename Func,
typename Derived>
191 struct redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>
193 typedef typename Derived::Scalar Scalar;
195 static EIGEN_STRONG_INLINE Scalar run(
const Derived &mat,
const Func& func)
197 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
199 res = mat.coeffByOuterInner(0, 0);
200 for(Index i = 1; i < mat.innerSize(); ++i)
201 res = func(res, mat.coeffByOuterInner(0, i));
202 for(Index i = 1; i < mat.outerSize(); ++i)
203 for(Index j = 0; j < mat.innerSize(); ++j)
204 res = func(res, mat.coeffByOuterInner(i, j));
209 template<
typename Func,
typename Derived>
210 struct redux_impl<Func,Derived, DefaultTraversal, CompleteUnrolling>
211 :
public redux_novec_unroller<Func,Derived, 0, Derived::SizeAtCompileTime>
214 template<
typename Func,
typename Derived>
215 struct redux_impl<Func, Derived, LinearVectorizedTraversal, NoUnrolling>
217 typedef typename Derived::Scalar Scalar;
218 typedef typename packet_traits<Scalar>::type PacketScalar;
220 static Scalar run(
const Derived &mat,
const Func& func)
222 const Index size = mat.size();
224 const Index packetSize = packet_traits<Scalar>::size;
225 const int packetAlignment = unpacket_traits<PacketScalar>::alignment;
227 alignment0 = (bool(Derived::Flags &
DirectAccessBit) && bool(packet_traits<Scalar>::AlignedOnScalar)) ?
int(packetAlignment) : int(
Unaligned),
228 alignment = EIGEN_PLAIN_ENUM_MAX(alignment0, Derived::Alignment)
230 const Index alignedStart = internal::first_default_aligned(mat.nestedExpression());
231 const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize);
232 const Index alignedSize = ((size-alignedStart)/(packetSize))*(packetSize);
233 const Index alignedEnd2 = alignedStart + alignedSize2;
234 const Index alignedEnd = alignedStart + alignedSize;
238 PacketScalar packet_res0 = mat.template packet<alignment,PacketScalar>(alignedStart);
239 if(alignedSize>packetSize)
241 PacketScalar packet_res1 = mat.template packet<alignment,PacketScalar>(alignedStart+packetSize);
242 for(Index index = alignedStart + 2*packetSize; index < alignedEnd2; index += 2*packetSize)
244 packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment,PacketScalar>(index));
245 packet_res1 = func.packetOp(packet_res1, mat.template packet<alignment,PacketScalar>(index+packetSize));
248 packet_res0 = func.packetOp(packet_res0,packet_res1);
249 if(alignedEnd>alignedEnd2)
250 packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment,PacketScalar>(alignedEnd2));
252 res = func.predux(packet_res0);
254 for(Index index = 0; index < alignedStart; ++index)
255 res = func(res,mat.coeff(index));
257 for(Index index = alignedEnd; index < size; ++index)
258 res = func(res,mat.coeff(index));
264 for(Index index = 1; index < size; ++index)
265 res = func(res,mat.coeff(index));
272 template<
typename Func,
typename Derived>
273 struct redux_impl<Func, Derived, SliceVectorizedTraversal, NoUnrolling>
275 typedef typename Derived::Scalar Scalar;
276 typedef typename packet_traits<Scalar>::type PacketType;
278 EIGEN_DEVICE_FUNC
static Scalar run(
const Derived &mat,
const Func& func)
280 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
281 const Index innerSize = mat.innerSize();
282 const Index outerSize = mat.outerSize();
284 packetSize = packet_traits<Scalar>::size
286 const Index packetedInnerSize = ((innerSize)/packetSize)*packetSize;
288 if(packetedInnerSize)
290 PacketType packet_res = mat.template packet<Unaligned,PacketType>(0,0);
291 for(Index j=0; j<outerSize; ++j)
292 for(Index i=(j==0?packetSize:0); i<packetedInnerSize; i+=Index(packetSize))
293 packet_res = func.packetOp(packet_res, mat.template packetByOuterInner<Unaligned,PacketType>(j,i));
295 res = func.predux(packet_res);
296 for(Index j=0; j<outerSize; ++j)
297 for(Index i=packetedInnerSize; i<innerSize; ++i)
298 res = func(res, mat.coeffByOuterInner(j,i));
303 res = redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>::run(mat, func);
310 template<
typename Func,
typename Derived>
311 struct redux_impl<Func, Derived, LinearVectorizedTraversal, CompleteUnrolling>
313 typedef typename Derived::Scalar Scalar;
314 typedef typename packet_traits<Scalar>::type PacketScalar;
316 PacketSize = packet_traits<Scalar>::size,
317 Size = Derived::SizeAtCompileTime,
318 VectorizedSize = (Size / PacketSize) * PacketSize
320 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE Scalar run(
const Derived &mat,
const Func& func)
322 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
323 if (VectorizedSize > 0) {
324 Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func));
325 if (VectorizedSize != Size)
326 res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
330 return redux_novec_unroller<Func, Derived, 0, Size>::run(mat,func);
336 template<
typename _XprType>
337 class redux_evaluator
340 typedef _XprType XprType;
341 EIGEN_DEVICE_FUNC
explicit redux_evaluator(
const XprType &xpr) : m_evaluator(xpr), m_xpr(xpr) {}
343 typedef typename XprType::Scalar Scalar;
344 typedef typename XprType::CoeffReturnType CoeffReturnType;
345 typedef typename XprType::PacketScalar PacketScalar;
346 typedef typename XprType::PacketReturnType PacketReturnType;
349 MaxRowsAtCompileTime = XprType::MaxRowsAtCompileTime,
350 MaxColsAtCompileTime = XprType::MaxColsAtCompileTime,
353 IsRowMajor = XprType::IsRowMajor,
354 SizeAtCompileTime = XprType::SizeAtCompileTime,
355 InnerSizeAtCompileTime = XprType::InnerSizeAtCompileTime,
356 CoeffReadCost = evaluator<XprType>::CoeffReadCost,
357 Alignment = evaluator<XprType>::Alignment
360 EIGEN_DEVICE_FUNC Index rows()
const {
return m_xpr.rows(); }
361 EIGEN_DEVICE_FUNC Index cols()
const {
return m_xpr.cols(); }
362 EIGEN_DEVICE_FUNC Index size()
const {
return m_xpr.size(); }
363 EIGEN_DEVICE_FUNC Index innerSize()
const {
return m_xpr.innerSize(); }
364 EIGEN_DEVICE_FUNC Index outerSize()
const {
return m_xpr.outerSize(); }
367 CoeffReturnType coeff(Index row, Index col)
const
368 {
return m_evaluator.coeff(row, col); }
371 CoeffReturnType coeff(Index index)
const
372 {
return m_evaluator.coeff(index); }
374 template<
int LoadMode,
typename PacketType>
375 PacketReturnType packet(Index row, Index col)
const
376 {
return m_evaluator.template packet<LoadMode,PacketType>(row, col); }
378 template<
int LoadMode,
typename PacketType>
379 PacketReturnType packet(Index index)
const
380 {
return m_evaluator.template packet<LoadMode,PacketType>(index); }
383 CoeffReturnType coeffByOuterInner(Index outer, Index inner)
const
384 {
return m_evaluator.coeff(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
386 template<
int LoadMode,
typename PacketType>
387 PacketReturnType packetByOuterInner(Index outer, Index inner)
const
388 {
return m_evaluator.template packet<LoadMode,PacketType>(IsRowMajor ? outer : inner, IsRowMajor ? inner : outer); }
390 const XprType & nestedExpression()
const {
return m_xpr; }
393 internal::evaluator<XprType> m_evaluator;
394 const XprType &m_xpr;
411 template<
typename Derived>
412 template<
typename Func>
413 typename internal::traits<Derived>::Scalar
416 eigen_assert(this->rows()>0 && this->cols()>0 &&
"you are using an empty matrix");
428 typedef typename internal::redux_evaluator<Derived> ThisEvaluator;
429 ThisEvaluator thisEval(derived());
431 return internal::redux_impl<Func, ThisEvaluator>::run(thisEval, func);
437 template<
typename Derived>
438 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
441 return derived().redux(Eigen::internal::scalar_min_op<Scalar>());
447 template<
typename Derived>
448 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
451 return derived().redux(Eigen::internal::scalar_max_op<Scalar>());
458 template<
typename Derived>
459 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
462 if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
464 return derived().redux(Eigen::internal::scalar_sum_op<Scalar>());
471 template<
typename Derived>
472 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
475 return Scalar(derived().redux(Eigen::internal::scalar_sum_op<Scalar>())) / Scalar(this->size());
485 template<
typename Derived>
486 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
489 if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
491 return derived().redux(Eigen::internal::scalar_product_op<Scalar>());
500 template<
typename Derived>
501 EIGEN_STRONG_INLINE
typename internal::traits<Derived>::Scalar
504 return derived().diagonal().sum();
509 #endif // EIGEN_REDUX_H
Scalar prod() const
Definition: Redux.h:487
const unsigned int DirectAccessBit
Definition: Constants.h:141
Definition: Constants.h:220
internal::traits< Derived >::Scalar maxCoeff() const
Definition: Redux.h:449
Definition: StdDeque.h:58
Base class for all dense matrices, vectors, and arrays.
Definition: DenseBase.h:41
Scalar mean() const
Definition: Redux.h:473
Scalar sum() const
Definition: Redux.h:460
internal::traits< Derived >::Scalar minCoeff() const
Definition: Redux.h:439
Definition: Eigen_Colamd.h:54
Scalar trace() const
Definition: Redux.h:502
const unsigned int ActualPacketAccessBit
Definition: Constants.h:91
const unsigned int LinearAccessBit
Definition: Constants.h:116