Loading...
Searching...
No Matches
TensorFunctors.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
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_CXX11_TENSOR_TENSOR_FUNCTORS_H
11#define EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
12
13namespace Eigen {
14namespace internal {
15
16
20template <typename Scalar>
21struct scalar_mod_op {
22 EIGEN_DEVICE_FUNC scalar_mod_op(const Scalar& divisor) : m_divisor(divisor) {}
23 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a % m_divisor; }
24 const Scalar m_divisor;
25};
26template <typename Scalar>
27struct functor_traits<scalar_mod_op<Scalar> >
28{ enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
29
30
34template <typename Scalar>
35struct scalar_mod2_op {
36 EIGEN_EMPTY_STRUCT_CTOR(scalar_mod2_op);
37 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a, const Scalar& b) const { return a % b; }
38};
39template <typename Scalar>
40struct functor_traits<scalar_mod2_op<Scalar> >
41{ enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
42
43template <typename Scalar>
44struct scalar_fmod_op {
45 EIGEN_EMPTY_STRUCT_CTOR(scalar_fmod_op);
46 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar
47 operator()(const Scalar& a, const Scalar& b) const {
48 return numext::fmod(a, b);
49 }
50};
51template <typename Scalar>
52struct functor_traits<scalar_fmod_op<Scalar> > {
53 enum { Cost = 13, // Reciprocal throughput of FPREM on Haswell.
54 PacketAccess = false };
55};
56
57
62template <typename T>
63struct scalar_sigmoid_op {
64 EIGEN_EMPTY_STRUCT_CTOR(scalar_sigmoid_op)
65 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const {
66 const T one = T(1);
67 return one / (one + numext::exp(-x));
68 }
69
70 template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
71 Packet packetOp(const Packet& x) const {
72 const Packet one = pset1<Packet>(T(1));
73 return pdiv(one, padd(one, pexp(pnegate(x))));
74 }
75};
76
77template <typename T>
78struct functor_traits<scalar_sigmoid_op<T> > {
79 enum {
80 Cost = NumTraits<T>::AddCost * 2 + NumTraits<T>::MulCost * 6,
81 PacketAccess = packet_traits<T>::HasAdd && packet_traits<T>::HasDiv &&
82 packet_traits<T>::HasNegate && packet_traits<T>::HasExp
83 };
84};
85
86
87template<typename Reducer, typename Device>
88struct reducer_traits {
89 enum {
90 Cost = 1,
91 PacketAccess = false
92 };
93};
94
95// Standard reduction functors
96template <typename T> struct SumReducer
97{
98 static const bool PacketAccess = packet_traits<T>::HasAdd;
99 static const bool IsStateful = false;
100
101 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
102 internal::scalar_sum_op<T> sum_op;
103 *accum = sum_op(*accum, t);
104 }
105 template <typename Packet>
106 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
107 (*accum) = padd<Packet>(*accum, p);
108 }
109
110 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
111 internal::scalar_cast_op<int, T> conv;
112 return conv(0);
113 }
114 template <typename Packet>
115 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
116 return pset1<Packet>(initialize());
117 }
118 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
119 return accum;
120 }
121 template <typename Packet>
122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
123 return vaccum;
124 }
125 template <typename Packet>
126 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
127 internal::scalar_sum_op<T> sum_op;
128 return sum_op(saccum, predux(vaccum));
129 }
130};
131
132template <typename T, typename Device>
133struct reducer_traits<SumReducer<T>, Device> {
134 enum {
135 Cost = NumTraits<T>::AddCost,
136 PacketAccess = PacketType<T, Device>::HasAdd
137 };
138};
139
140
141template <typename T> struct MeanReducer
142{
143 static const bool PacketAccess = packet_traits<T>::HasAdd && !NumTraits<T>::IsInteger;
144 static const bool IsStateful = true;
145
146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
147 MeanReducer() : scalarCount_(0), packetCount_(0) { }
148
149 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) {
150 internal::scalar_sum_op<T> sum_op;
151 *accum = sum_op(*accum, t);
152 scalarCount_++;
153 }
154 template <typename Packet>
155 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) {
156 (*accum) = padd<Packet>(*accum, p);
157 packetCount_++;
158 }
159
160 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
161 internal::scalar_cast_op<int, T> conv;
162 return conv(0);
163 }
164 template <typename Packet>
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
166 return pset1<Packet>(initialize());
167 }
168 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
169 return accum / scalarCount_;
170 }
171 template <typename Packet>
172 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
173 return pdiv(vaccum, pset1<Packet>(packetCount_));
174 }
175 template <typename Packet>
176 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
177 internal::scalar_sum_op<T> sum_op;
178 return sum_op(saccum, predux(vaccum)) / (scalarCount_ + packetCount_ * unpacket_traits<Packet>::size);
179 }
180
181 protected:
182 DenseIndex scalarCount_;
183 DenseIndex packetCount_;
184};
185
186template <typename T, typename Device>
187struct reducer_traits<MeanReducer<T>, Device> {
188 enum {
189 Cost = NumTraits<T>::AddCost,
190 PacketAccess = PacketType<T, Device>::HasAdd
191 };
192};
193
194
195template <typename T, bool IsMax = true, bool IsInteger = true>
196struct MinMaxBottomValue {
197 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
198 return Eigen::NumTraits<T>::lowest();
199 }
200};
201template <typename T>
202struct MinMaxBottomValue<T, true, false> {
203 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
204 return -Eigen::NumTraits<T>::infinity();
205 }
206};
207template <typename T>
208struct MinMaxBottomValue<T, false, true> {
209 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
210 return Eigen::NumTraits<T>::highest();
211 }
212};
213template <typename T>
214struct MinMaxBottomValue<T, false, false> {
215 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
216 return Eigen::NumTraits<T>::infinity();
217 }
218};
219
220
221template <typename T> struct MaxReducer
222{
223 static const bool PacketAccess = packet_traits<T>::HasMax;
224 static const bool IsStateful = false;
225
226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
227 if (t > *accum) { *accum = t; }
228 }
229 template <typename Packet>
230 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
231 (*accum) = pmax<Packet>(*accum, p);
232 }
233 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
234 return MinMaxBottomValue<T, true, Eigen::NumTraits<T>::IsInteger>::bottom_value();
235 }
236 template <typename Packet>
237 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
238 return pset1<Packet>(initialize());
239 }
240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
241 return accum;
242 }
243 template <typename Packet>
244 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
245 return vaccum;
246 }
247 template <typename Packet>
248 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
249 return numext::maxi(saccum, predux_max(vaccum));
250 }
251};
252
253template <typename T, typename Device>
254struct reducer_traits<MaxReducer<T>, Device> {
255 enum {
256 Cost = NumTraits<T>::AddCost,
257 PacketAccess = PacketType<T, Device>::HasMax
258 };
259};
260
261
262template <typename T> struct MinReducer
263{
264 static const bool PacketAccess = packet_traits<T>::HasMin;
265 static const bool IsStateful = false;
266
267 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
268 if (t < *accum) { *accum = t; }
269 }
270 template <typename Packet>
271 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
272 (*accum) = pmin<Packet>(*accum, p);
273 }
274 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
275 return MinMaxBottomValue<T, false, Eigen::NumTraits<T>::IsInteger>::bottom_value();
276 }
277 template <typename Packet>
278 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
279 return pset1<Packet>(initialize());
280 }
281 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
282 return accum;
283 }
284 template <typename Packet>
285 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
286 return vaccum;
287 }
288 template <typename Packet>
289 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
290 return numext::mini(saccum, predux_min(vaccum));
291 }
292};
293
294template <typename T, typename Device>
295struct reducer_traits<MinReducer<T>, Device> {
296 enum {
297 Cost = NumTraits<T>::AddCost,
298 PacketAccess = PacketType<T, Device>::HasMin
299 };
300};
301
302
303template <typename T> struct ProdReducer
304{
305 static const bool PacketAccess = packet_traits<T>::HasMul;
306 static const bool IsStateful = false;
307
308 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
309 internal::scalar_product_op<T> prod_op;
310 (*accum) = prod_op(*accum, t);
311 }
312 template <typename Packet>
313 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
314 (*accum) = pmul<Packet>(*accum, p);
315 }
316
317 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
318 internal::scalar_cast_op<int, T> conv;
319 return conv(1);
320 }
321 template <typename Packet>
322 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
323 return pset1<Packet>(initialize());
324 }
325 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
326 return accum;
327 }
328 template <typename Packet>
329 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
330 return vaccum;
331 }
332 template <typename Packet>
333 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
334 internal::scalar_product_op<T> prod_op;
335 return prod_op(saccum, predux_mul(vaccum));
336 }
337};
338
339template <typename T, typename Device>
340struct reducer_traits<ProdReducer<T>, Device> {
341 enum {
342 Cost = NumTraits<T>::MulCost,
343 PacketAccess = PacketType<T, Device>::HasMul
344 };
345};
346
347
348struct AndReducer
349{
350 static const bool PacketAccess = false;
351 static const bool IsStateful = false;
352
353 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const {
354 *accum = *accum && t;
355 }
356 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const {
357 return true;
358 }
359 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const {
360 return accum;
361 }
362};
363
364template <typename Device>
365struct reducer_traits<AndReducer, Device> {
366 enum {
367 Cost = 1,
368 PacketAccess = false
369 };
370};
371
372
373struct OrReducer {
374 static const bool PacketAccess = false;
375 static const bool IsStateful = false;
376
377 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const {
378 *accum = *accum || t;
379 }
380 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const {
381 return false;
382 }
383 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const {
384 return accum;
385 }
386};
387
388template <typename Device>
389struct reducer_traits<OrReducer, Device> {
390 enum {
391 Cost = 1,
392 PacketAccess = false
393 };
394};
395
396
397// Argmin/Argmax reducers
398template <typename T> struct ArgMaxTupleReducer
399{
400 static const bool PacketAccess = false;
401 static const bool IsStateful = false;
402
403 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
404 if (t.second > accum->second) { *accum = t; }
405 }
406 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
407 return T(0, NumTraits<typename T::second_type>::lowest());
408 }
409 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const {
410 return accum;
411 }
412};
413
414template <typename T, typename Device>
415struct reducer_traits<ArgMaxTupleReducer<T>, Device> {
416 enum {
417 Cost = NumTraits<T>::AddCost,
418 PacketAccess = false
419 };
420};
421
422
423template <typename T> struct ArgMinTupleReducer
424{
425 static const bool PacketAccess = false;
426 static const bool IsStateful = false;
427
428 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T& t, T* accum) const {
429 if (t.second < accum->second) { *accum = t; }
430 }
431 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
432 return T(0, NumTraits<typename T::second_type>::highest());
433 }
434 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const {
435 return accum;
436 }
437};
438
439template <typename T, typename Device>
440struct reducer_traits<ArgMinTupleReducer<T>, Device> {
441 enum {
442 Cost = NumTraits<T>::AddCost,
443 PacketAccess = false
444 };
445};
446
447
448template <typename T, typename Index, size_t NumDims>
449class GaussianGenerator {
450 public:
451 static const bool PacketAccess = false;
452
453 EIGEN_DEVICE_FUNC GaussianGenerator(const array<T, NumDims>& means,
454 const array<T, NumDims>& std_devs)
455 : m_means(means)
456 {
457 for (size_t i = 0; i < NumDims; ++i) {
458 m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2;
459 }
460 }
461
462 EIGEN_DEVICE_FUNC T operator()(const array<Index, NumDims>& coordinates) const {
463 T tmp = T(0);
464 for (size_t i = 0; i < NumDims; ++i) {
465 T offset = coordinates[i] - m_means[i];
466 tmp += offset * offset / m_two_sigmas[i];
467 }
468 return numext::exp(-tmp);
469 }
470
471 private:
472 array<T, NumDims> m_means;
473 array<T, NumDims> m_two_sigmas;
474};
475
476template <typename T, typename Index, size_t NumDims>
477struct functor_traits<GaussianGenerator<T, Index, NumDims> > {
478 enum {
479 Cost = NumDims * (2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost +
480 functor_traits<scalar_quotient_op<T, T> >::Cost) +
481 functor_traits<scalar_exp_op<T> >::Cost,
482 PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess
483 };
484};
485
486} // end namespace internal
487} // end namespace Eigen
488
489#endif // EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
Namespace containing all symbols from the Eigen library.
Definition: AdolcForward:45