Eigen-unsupported  5.0.1-dev+284dcc12
 
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
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17namespace internal {
18
22template <typename Scalar>
23struct 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};
28template <typename Scalar>
29struct functor_traits<scalar_mod_op<Scalar> > {
30 enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess = false };
31};
32
36template <typename Scalar>
37struct scalar_mod2_op {
38 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const { return a % b; }
39};
40template <typename Scalar>
41struct functor_traits<scalar_mod2_op<Scalar> > {
42 enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess = false };
43};
44
45template <typename Scalar>
46struct 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};
51template <typename Scalar>
52struct functor_traits<scalar_fmod_op<Scalar> > {
53 enum {
54 Cost = 13, // Reciprocal throughput of FPREM on Haswell.
55 PacketAccess = false
56 };
57};
58
59template <typename Reducer, typename Device>
60struct reducer_traits {
61 enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
62};
63
64// Standard reduction functors
65template <typename T>
66struct 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
96template <typename T, typename Device>
97struct 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
106template <typename T>
107struct 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
149template <typename T, typename Device>
150struct 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
159template <typename T, bool IsMax = true, bool IsInteger = true>
160struct MinMaxBottomValue {
161 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::lowest(); }
162};
163template <typename T>
164struct MinMaxBottomValue<T, true, false> {
165 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return -Eigen::NumTraits<T>::infinity(); }
166};
167template <typename T>
168struct MinMaxBottomValue<T, false, true> {
169 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::highest(); }
170};
171template <typename T>
172struct MinMaxBottomValue<T, false, false> {
173 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::infinity(); }
174};
175
176template <typename T, int NaNPropagation = PropagateFast>
177struct 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
206template <typename T, typename Device, int NaNPropagation>
207struct 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
216template <typename T, int NaNPropagation = PropagateFast>
217struct 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
246template <typename T, typename Device, int NaNPropagation>
247struct 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
256template <typename T>
257struct 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
286template <typename T, typename Device>
287struct 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
296struct 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
302template <typename Device>
303struct reducer_traits<AndReducer, Device> {
304 enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
305};
306
307struct 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
313template <typename Device>
314struct 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.
320template <typename T>
321struct 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
335template <typename T, typename Device>
336struct reducer_traits<ArgMaxPairReducer<T>, Device> {
337 enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
338};
339
340template <typename T>
341struct 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
355template <typename T, typename Device>
356struct reducer_traits<ArgMinPairReducer<T>, Device> {
357 enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
358};
359
360template <typename T, typename Index, size_t NumDims>
361class 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
388template <typename T, typename Index, size_t NumDims>
389struct 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
398template <typename Scalar>
399struct 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};
411template <typename Scalar>
412struct 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