11#ifndef EIGEN_TENSOR_TENSOR_FUNCTORS_H
12#define EIGEN_TENSOR_TENSOR_FUNCTORS_H
15#include "./InternalHeaderCheck.h"
23template <
typename Scalar>
25 EIGEN_DEVICE_FUNC scalar_mod_op(
const Scalar& divisor) : m_divisor(divisor) {}
26 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(
const Scalar& a)
const {
return a % m_divisor; }
27 const Scalar m_divisor;
29template <
typename Scalar>
30struct functor_traits<scalar_mod_op<Scalar>> {
31 enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess =
false };
37template <
typename Scalar>
38struct scalar_mod2_op {
39 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(
const Scalar& a,
const Scalar& b)
const {
return a % b; }
41template <
typename Scalar>
42struct functor_traits<scalar_mod2_op<Scalar>> {
43 enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess =
false };
46template <
typename Scalar>
47struct scalar_fmod_op {
48 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(
const Scalar& a,
const Scalar& b)
const {
49 return numext::fmod(a, b);
52template <
typename Scalar>
53struct functor_traits<scalar_fmod_op<Scalar>> {
60template <
typename Reducer,
typename Device>
61struct reducer_traits {
62 enum { Cost = 1, PacketAccess =
false, IsStateful =
false, IsExactlyAssociative =
true };
75template <
typename Reducer>
76struct reducer_can_reorder_accumulators : std::false_type {};
81 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum)
const {
82 internal::scalar_sum_op<T> sum_op;
83 *accum = sum_op(*accum, t);
85 template <
typename Packet>
86 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reducePacket(
const Packet& p, Packet* accum)
const {
87 (*accum) = padd<Packet>(*accum, p);
90 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
91 internal::scalar_cast_op<int, T> conv;
94 template <
typename Packet>
95 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket()
const {
96 return pset1<Packet>(initialize());
98 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T accum)
const {
return accum; }
99 template <
typename Packet>
100 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(
const Packet& vaccum)
const {
103 template <
typename Packet>
104 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(
const T saccum,
const Packet& vaccum)
const {
105 internal::scalar_sum_op<T> sum_op;
106 return sum_op(saccum, predux(vaccum));
110template <
typename T,
typename Device>
111struct reducer_traits<SumReducer<T>, Device> {
113 Cost = NumTraits<T>::AddCost,
114 PacketAccess = PacketType<T, Device>::HasAdd,
116 IsExactlyAssociative = NumTraits<T>::IsInteger
122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MeanReducer() =
default;
124 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum) {
125 internal::scalar_sum_op<T> sum_op;
126 *accum = sum_op(*accum, t);
129 template <
typename Packet>
130 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reducePacket(
const Packet& p, Packet* accum) {
131 (*accum) = padd<Packet>(*accum, p);
135 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
136 internal::scalar_cast_op<int, T> conv;
139 template <
typename Packet>
140 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket()
const {
141 return pset1<Packet>(initialize());
143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T accum)
const {
144 internal::scalar_quotient_op<T> quotient_op;
145 return quotient_op(accum, T(scalarCount_));
147 template <
typename Packet>
148 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(
const Packet& vaccum)
const {
149 return pdiv(vaccum, pset1<Packet>(T(packetCount_)));
151 template <
typename Packet>
152 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(
const T saccum,
const Packet& vaccum)
const {
153 internal::scalar_sum_op<T> sum_op;
154 internal::scalar_quotient_op<T> quotient_op;
155 return quotient_op(sum_op(saccum, predux(vaccum)), T(scalarCount_ + packetCount_ * unpacket_traits<Packet>::size));
159 DenseIndex scalarCount_ = 0;
160 DenseIndex packetCount_ = 0;
163template <
typename T,
typename Device>
164struct reducer_traits<MeanReducer<T>, Device> {
166 Cost = NumTraits<T>::AddCost,
167 PacketAccess = PacketType<T, Device>::HasAdd && PacketType<T, Device>::HasDiv && !NumTraits<T>::IsInteger,
169 IsExactlyAssociative = NumTraits<T>::IsInteger
173template <
typename T,
bool IsMax = true,
bool IsInteger = true>
174struct MinMaxBottomValue {
175 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE T bottom_value() {
return Eigen::NumTraits<T>::lowest(); }
178struct MinMaxBottomValue<T, true, false> {
179 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE T bottom_value() {
return -Eigen::NumTraits<T>::infinity(); }
182struct MinMaxBottomValue<T, false, true> {
183 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE T bottom_value() {
return Eigen::NumTraits<T>::highest(); }
186struct MinMaxBottomValue<T, false, false> {
187 EIGEN_DEVICE_FUNC
static EIGEN_STRONG_INLINE T bottom_value() {
return Eigen::NumTraits<T>::infinity(); }
190template <
typename T,
int NaNPropagation = PropagateFast>
192 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum)
const {
193 scalar_max_op<T, T, NaNPropagation> op;
194 *accum = op(t, *accum);
196 template <
typename Packet>
197 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reducePacket(
const Packet& p, Packet* accum)
const {
198 scalar_max_op<T, T, NaNPropagation> op;
199 (*accum) = op.packetOp(*accum, p);
201 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
202 return MinMaxBottomValue<T,
true, Eigen::NumTraits<T>::IsInteger>::bottom_value();
204 template <
typename Packet>
205 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket()
const {
206 return pset1<Packet>(initialize());
208 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T accum)
const {
return accum; }
209 template <
typename Packet>
210 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(
const Packet& vaccum)
const {
213 template <
typename Packet>
214 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(
const T saccum,
const Packet& vaccum)
const {
215 scalar_max_op<T, T, NaNPropagation> op;
216 return op(saccum, op.predux(vaccum));
220template <
typename T,
typename Device,
int NaNPropagation>
221struct reducer_traits<MaxReducer<T, NaNPropagation>, Device> {
223 Cost = NumTraits<T>::AddCost,
224 PacketAccess = PacketType<T, Device>::HasMax,
230template <
typename T,
int NaNPropagation = PropagateFast>
232 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum)
const {
233 scalar_min_op<T, T, NaNPropagation> op;
234 *accum = op(t, *accum);
236 template <
typename Packet>
237 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reducePacket(
const Packet& p, Packet* accum)
const {
238 scalar_min_op<T, T, NaNPropagation> op;
239 (*accum) = op.packetOp(*accum, p);
241 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
242 return MinMaxBottomValue<T,
false, Eigen::NumTraits<T>::IsInteger>::bottom_value();
244 template <
typename Packet>
245 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket()
const {
246 return pset1<Packet>(initialize());
248 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T accum)
const {
return accum; }
249 template <
typename Packet>
250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(
const Packet& vaccum)
const {
253 template <
typename Packet>
254 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(
const T saccum,
const Packet& vaccum)
const {
255 scalar_min_op<T, T, NaNPropagation> op;
256 return op(saccum, op.predux(vaccum));
260template <
typename T,
typename Device,
int NaNPropagation>
261struct reducer_traits<MinReducer<T, NaNPropagation>, Device> {
263 Cost = NumTraits<T>::AddCost,
264 PacketAccess = PacketType<T, Device>::HasMin,
272 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum)
const {
273 internal::scalar_product_op<T> prod_op;
274 (*accum) = prod_op(*accum, t);
276 template <
typename Packet>
277 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reducePacket(
const Packet& p, Packet* accum)
const {
278 (*accum) = pmul<Packet>(*accum, p);
280 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
281 internal::scalar_cast_op<int, T> conv;
284 template <
typename Packet>
285 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket()
const {
286 return pset1<Packet>(initialize());
288 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T accum)
const {
return accum; }
289 template <
typename Packet>
290 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(
const Packet& vaccum)
const {
293 template <
typename Packet>
294 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(
const T saccum,
const Packet& vaccum)
const {
295 internal::scalar_product_op<T> prod_op;
296 return prod_op(saccum, predux_mul(vaccum));
300template <
typename T,
typename Device>
301struct reducer_traits<ProdReducer<T>, Device> {
303 Cost = NumTraits<T>::MulCost,
304 PacketAccess = PacketType<T, Device>::HasMul,
306 IsExactlyAssociative =
true
313 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
bool t,
bool* accum)
const { *accum = *accum & t; }
314 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool initialize()
const {
return true; }
315 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool finalize(
bool accum)
const {
return accum; }
318template <
typename Device>
319struct reducer_traits<AndReducer, Device> {
320 enum { Cost = 1, PacketAccess =
false, IsStateful =
false, IsExactlyAssociative =
true };
324 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
bool t,
bool* accum)
const { *accum = *accum | t; }
325 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool initialize()
const {
return false; }
326 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool finalize(
bool accum)
const {
return accum; }
329template <
typename Device>
330struct reducer_traits<OrReducer, Device> {
331 enum { Cost = 1, PacketAccess =
false, IsStateful =
false, IsExactlyAssociative =
true };
337struct reducer_can_reorder_accumulators<SumReducer<T>>
338 : bool_constant<internal::is_arithmetic<T>::value || NumTraits<T>::IsComplex> {};
340struct reducer_can_reorder_accumulators<ProdReducer<T>>
341 : bool_constant<internal::is_arithmetic<T>::value || NumTraits<T>::IsComplex> {};
342template <
typename T,
int NaNPropagation>
343struct reducer_can_reorder_accumulators<MinReducer<T, NaNPropagation>> : internal::is_arithmetic<T> {};
344template <
typename T,
int NaNPropagation>
345struct reducer_can_reorder_accumulators<MaxReducer<T, NaNPropagation>> : internal::is_arithmetic<T> {};
347struct reducer_can_reorder_accumulators<AndReducer> : std::true_type {};
349struct reducer_can_reorder_accumulators<OrReducer> : std::true_type {};
354struct ArgMaxPairReducer {
355 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T t, T* accum)
const {
356 if (t.second < accum->second) {
358 }
else if (t.second > accum->second || accum->first > t.first) {
362 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
363 return T(0, NumTraits<typename T::second_type>::lowest());
365 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T& accum)
const {
return accum; }
368template <
typename T,
typename Device>
369struct reducer_traits<ArgMaxPairReducer<T>, Device> {
370 enum { Cost = NumTraits<T>::AddCost, PacketAccess =
false, IsStateful =
false, IsExactlyAssociative =
true };
374struct ArgMinPairReducer {
375 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void reduce(
const T& t, T* accum)
const {
376 if (t.second > accum->second) {
378 }
else if (t.second < accum->second || accum->first > t.first) {
382 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize()
const {
383 return T(0, NumTraits<typename T::second_type>::highest());
385 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(
const T& accum)
const {
return accum; }
388template <
typename T,
typename Device>
389struct reducer_traits<ArgMinPairReducer<T>, Device> {
390 enum { Cost = NumTraits<T>::AddCost, PacketAccess =
false, IsStateful =
false, IsExactlyAssociative =
true };
393template <
typename T,
typename Index,
size_t NumDims>
394class GaussianGenerator {
396 static constexpr bool PacketAccess =
false;
398 EIGEN_DEVICE_FUNC GaussianGenerator(
const array<T, NumDims>& means,
const array<T, NumDims>& std_devs)
401 for (
size_t i = 0; i < NumDims; ++i) {
402 m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2;
406 EIGEN_DEVICE_FUNC T operator()(
const array<Index, NumDims>& coordinates)
const {
409 for (
size_t i = 0; i < NumDims; ++i) {
410 T offset = coordinates[i] - m_means[i];
411 tmp += offset * offset / m_two_sigmas[i];
413 return numext::exp(-tmp);
417 array<T, NumDims> m_means;
418 array<T, NumDims> m_two_sigmas;
421template <
typename T,
typename Index,
size_t NumDims>
422struct functor_traits<GaussianGenerator<T, Index, NumDims>> {
425 NumDims * (2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost + functor_traits<scalar_quotient_op<T, T>>::Cost) +
426 functor_traits<scalar_exp_op<T>>::Cost,
427 PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess
431template <
typename Scalar>
432struct scalar_clamp_op {
433 EIGEN_DEVICE_FUNC
inline scalar_clamp_op(
const Scalar& _min,
const Scalar& _max) : m_min(_min), m_max(_max) {}
434 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Scalar operator()(
const Scalar& x)
const {
435 return numext::mini(numext::maxi(x, m_min), m_max);
437 template <
typename Packet>
438 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Packet packetOp(
const Packet& x)
const {
439 return internal::pmin(internal::pmax(x, pset1<Packet>(m_min)), pset1<Packet>(m_max));
444template <
typename Scalar>
445struct functor_traits<scalar_clamp_op<Scalar>> {
447 Cost = 2 * NumTraits<Scalar>::AddCost,
448 PacketAccess = (packet_traits<Scalar>::HasMin && packet_traits<Scalar>::HasMax)
Namespace containing all symbols from the Eigen library.