$darkmode
Eigen-unsupported  5.0.1-dev
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 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 namespace internal {
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 
45 template <typename Scalar>
46 struct scalar_fmod_op {
47  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar 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 {
54  Cost = 13, // Reciprocal throughput of FPREM on Haswell.
55  PacketAccess = false
56  };
57 };
58 
59 template <typename Reducer, typename Device>
60 struct reducer_traits {
61  enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
62 };
63 
64 // Standard reduction functors
65 template <typename T>
66 struct SumReducer {
67  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
68  internal::scalar_sum_op<T> sum_op;
69  *accum = sum_op(*accum, t);
70  }
71  template <typename Packet>
72  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
73  (*accum) = padd<Packet>(*accum, p);
74  }
75 
76  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
77  internal::scalar_cast_op<int, T> conv;
78  return conv(0);
79  }
80  template <typename Packet>
81  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
82  return pset1<Packet>(initialize());
83  }
84  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
85  template <typename Packet>
86  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
87  return vaccum;
88  }
89  template <typename Packet>
90  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
91  internal::scalar_sum_op<T> sum_op;
92  return sum_op(saccum, predux(vaccum));
93  }
94 };
95 
96 template <typename T, typename Device>
97 struct reducer_traits<SumReducer<T>, Device> {
98  enum {
99  Cost = NumTraits<T>::AddCost,
100  PacketAccess = PacketType<T, Device>::HasAdd,
101  IsStateful = false,
102  IsExactlyAssociative = NumTraits<T>::IsInteger
103  };
104 };
105 
106 template <typename T>
107 struct MeanReducer {
108  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MeanReducer() : scalarCount_(0), packetCount_(0) {}
109 
110  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) {
111  internal::scalar_sum_op<T> sum_op;
112  *accum = sum_op(*accum, t);
113  scalarCount_++;
114  }
115  template <typename Packet>
116  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) {
117  (*accum) = padd<Packet>(*accum, p);
118  packetCount_++;
119  }
120 
121  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
122  internal::scalar_cast_op<int, T> conv;
123  return conv(0);
124  }
125  template <typename Packet>
126  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
127  return pset1<Packet>(initialize());
128  }
129  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
130  internal::scalar_quotient_op<T> quotient_op;
131  return quotient_op(accum, T(scalarCount_));
132  }
133  template <typename Packet>
134  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
135  return pdiv(vaccum, pset1<Packet>(T(packetCount_)));
136  }
137  template <typename Packet>
138  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
139  internal::scalar_sum_op<T> sum_op;
140  internal::scalar_quotient_op<T> quotient_op;
141  return quotient_op(sum_op(saccum, predux(vaccum)), T(scalarCount_ + packetCount_ * unpacket_traits<Packet>::size));
142  }
143 
144  protected:
145  DenseIndex scalarCount_;
146  DenseIndex packetCount_;
147 };
148 
149 template <typename T, typename Device>
150 struct reducer_traits<MeanReducer<T>, Device> {
151  enum {
152  Cost = NumTraits<T>::AddCost,
153  PacketAccess = PacketType<T, Device>::HasAdd && PacketType<T, Device>::HasDiv && !NumTraits<T>::IsInteger,
154  IsStateful = true,
155  IsExactlyAssociative = NumTraits<T>::IsInteger
156  };
157 };
158 
159 template <typename T, bool IsMax = true, bool IsInteger = true>
160 struct MinMaxBottomValue {
161  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::lowest(); }
162 };
163 template <typename T>
164 struct MinMaxBottomValue<T, true, false> {
165  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return -Eigen::NumTraits<T>::infinity(); }
166 };
167 template <typename T>
168 struct MinMaxBottomValue<T, false, true> {
169  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::highest(); }
170 };
171 template <typename T>
172 struct MinMaxBottomValue<T, false, false> {
173  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::infinity(); }
174 };
175 
176 template <typename T, int NaNPropagation = PropagateFast>
177 struct MaxReducer {
178  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
179  scalar_max_op<T, T, NaNPropagation> op;
180  *accum = op(t, *accum);
181  }
182  template <typename Packet>
183  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
184  scalar_max_op<T, T, NaNPropagation> op;
185  (*accum) = op.packetOp(*accum, p);
186  }
187  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
188  return MinMaxBottomValue<T, /*IsMax=*/true, Eigen::NumTraits<T>::IsInteger>::bottom_value();
189  }
190  template <typename Packet>
191  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
192  return pset1<Packet>(initialize());
193  }
194  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
195  template <typename Packet>
196  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
197  return vaccum;
198  }
199  template <typename Packet>
200  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
201  scalar_max_op<T, T, NaNPropagation> op;
202  return op(saccum, op.predux(vaccum));
203  }
204 };
205 
206 template <typename T, typename Device, int NaNPropagation>
207 struct reducer_traits<MaxReducer<T, NaNPropagation>, Device> {
208  enum {
209  Cost = NumTraits<T>::AddCost,
210  PacketAccess = PacketType<T, Device>::HasMax,
211  IsStateful = false,
212  IsExactlyAssociative = (NaNPropagation != PropagateFast)
213  };
214 };
215 
216 template <typename T, int NaNPropagation = PropagateFast>
217 struct MinReducer {
218  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
219  scalar_min_op<T, T, NaNPropagation> op;
220  *accum = op(t, *accum);
221  }
222  template <typename Packet>
223  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
224  scalar_min_op<T, T, NaNPropagation> op;
225  (*accum) = op.packetOp(*accum, p);
226  }
227  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
228  return MinMaxBottomValue<T, /*IsMax=*/false, Eigen::NumTraits<T>::IsInteger>::bottom_value();
229  }
230  template <typename Packet>
231  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
232  return pset1<Packet>(initialize());
233  }
234  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
235  template <typename Packet>
236  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
237  return vaccum;
238  }
239  template <typename Packet>
240  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
241  scalar_min_op<T, T, NaNPropagation> op;
242  return op(saccum, op.predux(vaccum));
243  }
244 };
245 
246 template <typename T, typename Device, int NaNPropagation>
247 struct reducer_traits<MinReducer<T, NaNPropagation>, Device> {
248  enum {
249  Cost = NumTraits<T>::AddCost,
250  PacketAccess = PacketType<T, Device>::HasMin,
251  IsStateful = false,
252  IsExactlyAssociative = (NaNPropagation != PropagateFast)
253  };
254 };
255 
256 template <typename T>
257 struct ProdReducer {
258  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
259  internal::scalar_product_op<T> prod_op;
260  (*accum) = prod_op(*accum, t);
261  }
262  template <typename Packet>
263  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
264  (*accum) = pmul<Packet>(*accum, p);
265  }
266  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
267  internal::scalar_cast_op<int, T> conv;
268  return conv(1);
269  }
270  template <typename Packet>
271  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
272  return pset1<Packet>(initialize());
273  }
274  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
275  template <typename Packet>
276  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
277  return vaccum;
278  }
279  template <typename Packet>
280  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
281  internal::scalar_product_op<T> prod_op;
282  return prod_op(saccum, predux_mul(vaccum));
283  }
284 };
285 
286 template <typename T, typename Device>
287 struct reducer_traits<ProdReducer<T>, Device> {
288  enum {
289  Cost = NumTraits<T>::MulCost,
290  PacketAccess = PacketType<T, Device>::HasMul,
291  IsStateful = false,
292  IsExactlyAssociative = true
293  };
294 };
295 
296 struct AndReducer {
297  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { *accum = *accum && t; }
298  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { return true; }
299  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { return accum; }
300 };
301 
302 template <typename Device>
303 struct reducer_traits<AndReducer, Device> {
304  enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
305 };
306 
307 struct OrReducer {
308  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { *accum = *accum || t; }
309  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { return false; }
310  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { return accum; }
311 };
312 
313 template <typename Device>
314 struct reducer_traits<OrReducer, Device> {
315  enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
316 };
317 
318 // Argmin/Argmax reducers. Returns the first occurrence if multiple locations
319 // contain the same min/max value.
320 template <typename T>
321 struct ArgMaxPairReducer {
322  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
323  if (t.second < accum->second) {
324  return;
325  } else if (t.second > accum->second || accum->first > t.first) {
326  *accum = t;
327  }
328  }
329  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
330  return T(0, NumTraits<typename T::second_type>::lowest());
331  }
332  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { return accum; }
333 };
334 
335 template <typename T, typename Device>
336 struct reducer_traits<ArgMaxPairReducer<T>, Device> {
337  enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
338 };
339 
340 template <typename T>
341 struct ArgMinPairReducer {
342  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T& t, T* accum) const {
343  if (t.second > accum->second) {
344  return;
345  } else if (t.second < accum->second || accum->first > t.first) {
346  *accum = t;
347  }
348  }
349  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
350  return T(0, NumTraits<typename T::second_type>::highest());
351  }
352  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { return accum; }
353 };
354 
355 template <typename T, typename Device>
356 struct reducer_traits<ArgMinPairReducer<T>, Device> {
357  enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
358 };
359 
360 template <typename T, typename Index, size_t NumDims>
361 class GaussianGenerator {
362  public:
363  static constexpr bool PacketAccess = false;
364 
365  EIGEN_DEVICE_FUNC GaussianGenerator(const array<T, NumDims>& means, const array<T, NumDims>& std_devs)
366  : m_means(means) {
367  EIGEN_UNROLL_LOOP
368  for (size_t i = 0; i < NumDims; ++i) {
369  m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2;
370  }
371  }
372 
373  EIGEN_DEVICE_FUNC T operator()(const array<Index, NumDims>& coordinates) const {
374  T tmp = T(0);
375  EIGEN_UNROLL_LOOP
376  for (size_t i = 0; i < NumDims; ++i) {
377  T offset = coordinates[i] - m_means[i];
378  tmp += offset * offset / m_two_sigmas[i];
379  }
380  return numext::exp(-tmp);
381  }
382 
383  private:
384  array<T, NumDims> m_means;
385  array<T, NumDims> m_two_sigmas;
386 };
387 
388 template <typename T, typename Index, size_t NumDims>
389 struct functor_traits<GaussianGenerator<T, Index, NumDims> > {
390  enum {
391  Cost = NumDims *
392  (2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost + functor_traits<scalar_quotient_op<T, T> >::Cost) +
393  functor_traits<scalar_exp_op<T> >::Cost,
394  PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess
395  };
396 };
397 
398 template <typename Scalar>
399 struct scalar_clamp_op {
400  EIGEN_DEVICE_FUNC inline scalar_clamp_op(const Scalar& _min, const Scalar& _max) : m_min(_min), m_max(_max) {}
401  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& x) const {
402  return numext::mini(numext::maxi(x, m_min), m_max);
403  }
404  template <typename Packet>
405  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& x) const {
406  return internal::pmin(internal::pmax(x, pset1<Packet>(m_min)), pset1<Packet>(m_max));
407  }
408  const Scalar m_min;
409  const Scalar m_max;
410 };
411 template <typename Scalar>
412 struct functor_traits<scalar_clamp_op<Scalar> > {
413  enum {
414  Cost = 2 * NumTraits<Scalar>::AddCost,
415  PacketAccess = (packet_traits<Scalar>::HasMin && packet_traits<Scalar>::HasMax)
416  };
417 };
418 
419 } // end namespace internal
420 } // end namespace Eigen
421 
422 #endif // EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index