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