41 template<
typename Func,
typename Derived>
46 PacketSize = packet_traits<typename Derived::Scalar>::size,
47 InnerMaxSize =
int(Derived::IsRowMajor)
48 ? Derived::MaxColsAtCompileTime
49 : Derived::MaxRowsAtCompileTime
54 && (functor_traits<Func>::PacketAccess),
56 MaySliceVectorize = MightVectorize &&
int(InnerMaxSize)>=3*PacketSize
68 Cost = ( Derived::SizeAtCompileTime ==
Dynamic
69 || Derived::CoeffReadCost ==
Dynamic
70 || (Derived::SizeAtCompileTime!=1 && functor_traits<Func>::Cost ==
Dynamic)
72 : Derived::SizeAtCompileTime * Derived::CoeffReadCost
73 + (Derived::SizeAtCompileTime-1) * functor_traits<Func>::Cost,
79 Unrolling = Cost !=
Dynamic && Cost <= UnrollingLimit
91 template<
typename Func,
typename Derived,
int Start,
int Length>
92 struct redux_novec_unroller
98 typedef typename Derived::Scalar Scalar;
102 return func(redux_novec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
103 redux_novec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func));
107 template<
typename Func,
typename Derived,
int Start>
108 struct redux_novec_unroller<Func, Derived, Start, 1>
111 outer = Start / Derived::InnerSizeAtCompileTime,
112 inner = Start % Derived::InnerSizeAtCompileTime
115 typedef typename Derived::Scalar Scalar;
119 return mat.coeffByOuterInner(outer, inner);
126 template<
typename Func,
typename Derived,
int Start>
127 struct redux_novec_unroller<Func, Derived, Start, 0>
129 typedef typename Derived::Scalar Scalar;
135 template<
typename Func,
typename Derived,
int Start,
int Length>
136 struct redux_vec_unroller
139 PacketSize = packet_traits<typename Derived::Scalar>::size,
140 HalfLength = Length/2
143 typedef typename Derived::Scalar Scalar;
144 typedef typename packet_traits<Scalar>::type PacketScalar;
148 return func.packetOp(
149 redux_vec_unroller<Func, Derived, Start, HalfLength>::run(mat,func),
150 redux_vec_unroller<Func, Derived, Start+HalfLength, Length-HalfLength>::run(mat,func) );
154 template<
typename Func,
typename Derived,
int Start>
155 struct redux_vec_unroller<Func, Derived, Start, 1>
158 index = Start * packet_traits<typename Derived::Scalar>::size,
159 outer = index /
int(Derived::InnerSizeAtCompileTime),
160 inner = index %
int(Derived::InnerSizeAtCompileTime),
164 typedef typename Derived::Scalar Scalar;
165 typedef typename packet_traits<Scalar>::type PacketScalar;
169 return mat.template packetByOuterInner<alignment>(outer, inner);
177 template<
typename Func,
typename Derived,
178 int Traversal = redux_traits<Func, Derived>::Traversal,
179 int Unrolling = redux_traits<Func, Derived>::Unrolling
183 template<
typename Func,
typename Derived>
186 typedef typename Derived::Scalar Scalar;
187 typedef typename Derived::Index Index;
190 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
192 res = mat.coeffByOuterInner(0, 0);
193 for(Index i = 1; i < mat.innerSize(); ++i)
194 res = func(res, mat.coeffByOuterInner(0, i));
195 for(Index i = 1; i < mat.outerSize(); ++i)
196 for(Index j = 0; j < mat.innerSize(); ++j)
197 res = func(res, mat.coeffByOuterInner(i, j));
202 template<
typename Func,
typename Derived>
204 :
public redux_novec_unroller<Func,Derived, 0, Derived::SizeAtCompileTime>
207 template<
typename Func,
typename Derived>
210 typedef typename Derived::Scalar Scalar;
211 typedef typename packet_traits<Scalar>::type PacketScalar;
212 typedef typename Derived::Index Index;
214 static Scalar run(
const Derived& mat,
const Func& func)
216 const Index size = mat.size();
218 const Index packetSize = packet_traits<Scalar>::size;
219 const Index alignedStart = internal::first_aligned(mat);
224 const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize);
225 const Index alignedSize = ((size-alignedStart)/(packetSize))*(packetSize);
226 const Index alignedEnd2 = alignedStart + alignedSize2;
227 const Index alignedEnd = alignedStart + alignedSize;
231 PacketScalar packet_res0 = mat.template packet<alignment>(alignedStart);
232 if(alignedSize>packetSize)
234 PacketScalar packet_res1 = mat.template packet<alignment>(alignedStart+packetSize);
235 for(Index index = alignedStart + 2*packetSize; index < alignedEnd2; index += 2*packetSize)
237 packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment>(index));
238 packet_res1 = func.packetOp(packet_res1, mat.template packet<alignment>(index+packetSize));
241 packet_res0 = func.packetOp(packet_res0,packet_res1);
242 if(alignedEnd>alignedEnd2)
243 packet_res0 = func.packetOp(packet_res0, mat.template packet<alignment>(alignedEnd2));
245 res = func.predux(packet_res0);
247 for(Index index = 0; index < alignedStart; ++index)
248 res = func(res,mat.coeff(index));
250 for(Index index = alignedEnd; index < size; ++index)
251 res = func(res,mat.coeff(index));
257 for(Index index = 1; index < size; ++index)
258 res = func(res,mat.coeff(index));
265 template<
typename Func,
typename Derived>
268 typedef typename Derived::Scalar Scalar;
269 typedef typename packet_traits<Scalar>::type PacketScalar;
270 typedef typename Derived::Index Index;
272 static Scalar run(
const Derived& mat,
const Func& func)
274 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
275 const Index innerSize = mat.innerSize();
276 const Index outerSize = mat.outerSize();
278 packetSize = packet_traits<Scalar>::size
280 const Index packetedInnerSize = ((innerSize)/packetSize)*packetSize;
282 if(packetedInnerSize)
284 PacketScalar packet_res = mat.template packet<Unaligned>(0,0);
285 for(Index j=0; j<outerSize; ++j)
286 for(Index i=(j==0?packetSize:0); i<packetedInnerSize; i+=Index(packetSize))
287 packet_res = func.packetOp(packet_res, mat.template packetByOuterInner<Unaligned>(j,i));
289 res = func.predux(packet_res);
290 for(Index j=0; j<outerSize; ++j)
291 for(Index i=packetedInnerSize; i<innerSize; ++i)
292 res = func(res, mat.coeffByOuterInner(j,i));
297 res = redux_impl<Func, Derived, DefaultTraversal, NoUnrolling>::run(mat, func);
304 template<
typename Func,
typename Derived>
307 typedef typename Derived::Scalar Scalar;
308 typedef typename packet_traits<Scalar>::type PacketScalar;
310 PacketSize = packet_traits<Scalar>::size,
311 Size = Derived::SizeAtCompileTime,
312 VectorizedSize = (Size / PacketSize) * PacketSize
316 eigen_assert(mat.rows()>0 && mat.cols()>0 &&
"you are using an empty matrix");
317 Scalar res = func.predux(redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func));
318 if (VectorizedSize != Size)
319 res = func(res,redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
338 template<
typename Derived>
339 template<
typename Func>
340 EIGEN_STRONG_INLINE typename internal::result_of<Func(typename internal::traits<Derived>::Scalar)>::type
343 typedef typename internal::remove_all<typename Derived::Nested>::type ThisNested;
344 return internal::redux_impl<Func, ThisNested>
345 ::run(derived(), func);
350 template<
typename Derived>
354 return this->redux(Eigen::internal::scalar_min_op<Scalar>());
359 template<
typename Derived>
363 return this->redux(Eigen::internal::scalar_max_op<Scalar>());
370 template<
typename Derived>
374 if(SizeAtCompileTime==0 || (SizeAtCompileTime==
Dynamic && size()==0))
376 return this->redux(Eigen::internal::scalar_sum_op<Scalar>());
383 template<
typename Derived>
387 return Scalar(this->redux(Eigen::internal::scalar_sum_op<Scalar>())) /
Scalar(this->size());
397 template<
typename Derived>
401 if(SizeAtCompileTime==0 || (SizeAtCompileTime==
Dynamic && size()==0))
403 return this->redux(Eigen::internal::scalar_product_op<Scalar>());
412 template<
typename Derived>
421 #endif // EIGEN_REDUX_H