Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorFunctors.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
0005 //
0006 // This Source Code Form is subject to the terms of the Mozilla
0007 // Public License v. 2.0. If a copy of the MPL was not distributed
0008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0009 
0010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
0011 #define EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
0012 
0013 namespace Eigen {
0014 namespace internal {
0015 
0016 
0017 /** \internal
0018  * \brief Template functor to compute the modulo between an array and a scalar.
0019  */
0020 template <typename Scalar>
0021 struct scalar_mod_op {
0022   EIGEN_DEVICE_FUNC scalar_mod_op(const Scalar& divisor) : m_divisor(divisor) {}
0023   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a % m_divisor; }
0024   const Scalar m_divisor;
0025 };
0026 template <typename Scalar>
0027 struct functor_traits<scalar_mod_op<Scalar> >
0028 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
0029 
0030 
0031 /** \internal
0032  * \brief Template functor to compute the modulo between 2 arrays.
0033  */
0034 template <typename Scalar>
0035 struct scalar_mod2_op {
0036   EIGEN_EMPTY_STRUCT_CTOR(scalar_mod2_op)
0037   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a, const Scalar& b) const { return a % b; }
0038 };
0039 template <typename Scalar>
0040 struct functor_traits<scalar_mod2_op<Scalar> >
0041 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
0042 
0043 template <typename Scalar>
0044 struct scalar_fmod_op {
0045   EIGEN_EMPTY_STRUCT_CTOR(scalar_fmod_op)
0046   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar
0047   operator()(const Scalar& a, const Scalar& b) const {
0048     return numext::fmod(a, b);
0049   }
0050 };
0051 template <typename Scalar>
0052 struct functor_traits<scalar_fmod_op<Scalar> > {
0053   enum { Cost = 13,  // Reciprocal throughput of FPREM on Haswell.
0054          PacketAccess = false };
0055 };
0056 
0057 template<typename Reducer, typename Device>
0058 struct reducer_traits {
0059   enum {
0060     Cost = 1,
0061     PacketAccess = false,
0062     IsStateful = false,
0063     IsExactlyAssociative = true
0064   };
0065 };
0066 
0067 // Standard reduction functors
0068 template <typename T> struct SumReducer
0069 {
0070   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
0071     internal::scalar_sum_op<T> sum_op;
0072     *accum = sum_op(*accum, t);
0073   }
0074   template <typename Packet>
0075   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
0076     (*accum) = padd<Packet>(*accum, p);
0077   }
0078 
0079   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0080     internal::scalar_cast_op<int, T> conv;
0081     return conv(0);
0082   }
0083   template <typename Packet>
0084   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
0085     return pset1<Packet>(initialize());
0086   }
0087   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
0088     return accum;
0089   }
0090   template <typename Packet>
0091   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
0092     return vaccum;
0093   }
0094   template <typename Packet>
0095   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
0096     internal::scalar_sum_op<T> sum_op;
0097     return sum_op(saccum, predux(vaccum));
0098   }
0099 };
0100 
0101 template <typename T, typename Device>
0102 struct reducer_traits<SumReducer<T>, Device> {
0103   enum {
0104     Cost = NumTraits<T>::AddCost,
0105     PacketAccess = PacketType<T, Device>::HasAdd,
0106     IsStateful = false,
0107     IsExactlyAssociative = NumTraits<T>::IsInteger
0108   };
0109 };
0110 
0111 template <typename T> struct MeanReducer
0112 {
0113   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0114   MeanReducer() : scalarCount_(0), packetCount_(0) { }
0115 
0116   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) {
0117     internal::scalar_sum_op<T> sum_op;
0118     *accum = sum_op(*accum, t);
0119     scalarCount_++;
0120   }
0121   template <typename Packet>
0122   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) {
0123     (*accum) = padd<Packet>(*accum, p);
0124     packetCount_++;
0125   }
0126 
0127   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0128     internal::scalar_cast_op<int, T> conv;
0129     return conv(0);
0130   }
0131   template <typename Packet>
0132   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
0133     return pset1<Packet>(initialize());
0134   }
0135   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
0136     internal::scalar_quotient_op<T> quotient_op;
0137     return quotient_op(accum, T(scalarCount_));
0138   }
0139   template <typename Packet>
0140   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
0141     return pdiv(vaccum, pset1<Packet>(T(packetCount_)));
0142   }
0143   template <typename Packet>
0144   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
0145     internal::scalar_sum_op<T> sum_op;
0146     internal::scalar_quotient_op<T> quotient_op;
0147     return quotient_op(
0148         sum_op(saccum, predux(vaccum)),
0149         T(scalarCount_ + packetCount_ * unpacket_traits<Packet>::size));
0150   }
0151 
0152   protected:
0153     DenseIndex scalarCount_;
0154     DenseIndex packetCount_;
0155 };
0156 
0157 template <typename T, typename Device>
0158 struct reducer_traits<MeanReducer<T>, Device> {
0159   enum {
0160     Cost = NumTraits<T>::AddCost,
0161     PacketAccess = PacketType<T, Device>::HasAdd &&
0162                    PacketType<T, Device>::HasDiv && !NumTraits<T>::IsInteger,
0163     IsStateful = true,
0164     IsExactlyAssociative = NumTraits<T>::IsInteger
0165   };
0166 };
0167 
0168 
0169 template <typename T, bool IsMax = true, bool IsInteger = true>
0170 struct MinMaxBottomValue {
0171   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
0172     return Eigen::NumTraits<T>::lowest();
0173   }
0174 };
0175 template <typename T>
0176 struct MinMaxBottomValue<T, true, false> {
0177   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
0178     return -Eigen::NumTraits<T>::infinity();
0179   }
0180 };
0181 template <typename T>
0182 struct MinMaxBottomValue<T, false, true> {
0183   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
0184     return Eigen::NumTraits<T>::highest();
0185   }
0186 };
0187 template <typename T>
0188 struct MinMaxBottomValue<T, false, false> {
0189   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
0190     return Eigen::NumTraits<T>::infinity();
0191   }
0192 };
0193 
0194 
0195 template <typename T, int NaNPropagation=PropagateFast> struct MaxReducer
0196 {
0197   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
0198     scalar_max_op<T, T, NaNPropagation> op;
0199     *accum = op(t, *accum);
0200   }
0201   template <typename Packet>
0202   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
0203     scalar_max_op<T, T, NaNPropagation> op;
0204     (*accum) = op.packetOp(*accum, p);
0205   }
0206   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0207     return MinMaxBottomValue<T, /*IsMax=*/true, Eigen::NumTraits<T>::IsInteger>::bottom_value();
0208   }
0209   template <typename Packet>
0210   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
0211     return pset1<Packet>(initialize());
0212   }
0213   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
0214     return accum;
0215   }
0216   template <typename Packet>
0217   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
0218     return vaccum;
0219   }
0220   template <typename Packet>
0221   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
0222     scalar_max_op<T, T, NaNPropagation> op;
0223     return op(saccum, op.predux(vaccum));
0224   }
0225 };
0226 
0227 template <typename T, typename Device, int NaNPropagation>
0228     struct reducer_traits<MaxReducer<T, NaNPropagation>, Device> {
0229   enum {
0230     Cost = NumTraits<T>::AddCost,
0231     PacketAccess = PacketType<T, Device>::HasMax,
0232     IsStateful = false,
0233     IsExactlyAssociative = (NaNPropagation!=PropagateFast)
0234   };
0235 };
0236 
0237 template <typename T, int NaNPropagation=PropagateFast> struct MinReducer
0238 {
0239   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
0240     scalar_min_op<T, T, NaNPropagation> op;
0241     *accum = op(t, *accum);
0242   }
0243   template <typename Packet>
0244   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
0245     scalar_min_op<T, T, NaNPropagation> op;
0246     (*accum) = op.packetOp(*accum, p);
0247   }
0248   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0249     return MinMaxBottomValue<T, /*IsMax=*/false, Eigen::NumTraits<T>::IsInteger>::bottom_value();
0250   }
0251   template <typename Packet>
0252   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
0253     return pset1<Packet>(initialize());
0254   }
0255   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
0256     return accum;
0257   }
0258   template <typename Packet>
0259   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
0260     return vaccum;
0261   }
0262   template <typename Packet>
0263   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
0264     scalar_min_op<T, T, NaNPropagation> op;
0265     return op(saccum, op.predux(vaccum));
0266   }
0267 };
0268 
0269 template <typename T, typename Device, int NaNPropagation>
0270     struct reducer_traits<MinReducer<T, NaNPropagation>, Device> {
0271   enum {
0272     Cost = NumTraits<T>::AddCost,
0273     PacketAccess = PacketType<T, Device>::HasMin,
0274     IsStateful = false,
0275     IsExactlyAssociative = (NaNPropagation!=PropagateFast)
0276   };
0277 };
0278 
0279 template <typename T> struct ProdReducer
0280 {
0281   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
0282     internal::scalar_product_op<T> prod_op;
0283     (*accum) = prod_op(*accum, t);
0284   }
0285   template <typename Packet>
0286   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
0287     (*accum) = pmul<Packet>(*accum, p);
0288   }
0289   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0290     internal::scalar_cast_op<int, T> conv;
0291     return conv(1);
0292   }
0293   template <typename Packet>
0294   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
0295     return pset1<Packet>(initialize());
0296   }
0297   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
0298     return accum;
0299   }
0300   template <typename Packet>
0301   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
0302     return vaccum;
0303   }
0304   template <typename Packet>
0305   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
0306     internal::scalar_product_op<T> prod_op;
0307     return prod_op(saccum, predux_mul(vaccum));
0308   }
0309 };
0310 
0311 template <typename T, typename Device>
0312 struct reducer_traits<ProdReducer<T>, Device> {
0313   enum {
0314     Cost = NumTraits<T>::MulCost,
0315     PacketAccess = PacketType<T, Device>::HasMul,
0316     IsStateful = false,
0317     IsExactlyAssociative = true
0318   };
0319 };
0320 
0321 
0322 struct AndReducer
0323 {
0324   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const {
0325     *accum = *accum && t;
0326   }
0327   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const {
0328     return true;
0329   }
0330   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const {
0331     return accum;
0332   }
0333 };
0334 
0335 template <typename Device>
0336 struct reducer_traits<AndReducer, Device> {
0337   enum {
0338     Cost = 1,
0339     PacketAccess = false,
0340     IsStateful = false,
0341     IsExactlyAssociative = true
0342   };
0343 };
0344 
0345 
0346 struct OrReducer {
0347   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const {
0348     *accum = *accum || t;
0349   }
0350   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const {
0351     return false;
0352   }
0353   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const {
0354     return accum;
0355   }
0356 };
0357 
0358 template <typename Device>
0359 struct reducer_traits<OrReducer, Device> {
0360   enum {
0361     Cost = 1,
0362     PacketAccess = false,
0363     IsStateful = false,
0364     IsExactlyAssociative = true
0365   };
0366 };
0367 
0368 // Argmin/Argmax reducers.  Returns the first occurrence if multiple locations
0369 // contain the same min/max value.
0370 template <typename T> struct ArgMaxTupleReducer
0371 {
0372   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
0373     if (t.second < accum->second) {
0374       return;
0375     } else if (t.second > accum->second || accum->first > t.first ) {
0376       *accum = t;
0377     }
0378   }
0379   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0380     return T(0, NumTraits<typename T::second_type>::lowest());
0381   }
0382   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const {
0383     return accum;
0384   }
0385 };
0386 
0387 template <typename T, typename Device>
0388 struct reducer_traits<ArgMaxTupleReducer<T>, Device> {
0389   enum {
0390     Cost = NumTraits<T>::AddCost,
0391     PacketAccess = false,
0392     IsStateful = false,
0393     IsExactlyAssociative = true
0394   };
0395 };
0396 
0397 
0398 template <typename T> struct ArgMinTupleReducer
0399 {
0400   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T& t, T* accum) const {
0401     if (t.second > accum->second) {
0402       return;
0403     } else if (t.second < accum->second || accum->first > t.first) {
0404       *accum = t;
0405     }
0406   }
0407   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
0408     return T(0, NumTraits<typename T::second_type>::highest());
0409   }
0410   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const {
0411     return accum;
0412   }
0413 };
0414 
0415 template <typename T, typename Device>
0416 struct reducer_traits<ArgMinTupleReducer<T>, Device> {
0417   enum {
0418     Cost = NumTraits<T>::AddCost,
0419     PacketAccess = false,
0420     IsStateful = false,
0421     IsExactlyAssociative = true
0422   };
0423 };
0424 
0425 
0426 template <typename T, typename Index, size_t NumDims>
0427 class GaussianGenerator {
0428  public:
0429   static const bool PacketAccess = false;
0430 
0431   EIGEN_DEVICE_FUNC GaussianGenerator(const array<T, NumDims>& means,
0432                                       const array<T, NumDims>& std_devs)
0433       : m_means(means)
0434   {
0435     EIGEN_UNROLL_LOOP
0436     for (size_t i = 0; i < NumDims; ++i) {
0437       m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2;
0438     }
0439   }
0440 
0441   EIGEN_DEVICE_FUNC T operator()(const array<Index, NumDims>& coordinates) const {
0442     T tmp = T(0);
0443     EIGEN_UNROLL_LOOP
0444     for (size_t i = 0; i < NumDims; ++i) {
0445       T offset = coordinates[i] - m_means[i];
0446       tmp += offset * offset / m_two_sigmas[i];
0447     }
0448     return numext::exp(-tmp);
0449   }
0450 
0451  private:
0452   array<T, NumDims> m_means;
0453   array<T, NumDims> m_two_sigmas;
0454 };
0455 
0456 template <typename T, typename Index, size_t NumDims>
0457 struct functor_traits<GaussianGenerator<T, Index, NumDims> > {
0458   enum {
0459     Cost = NumDims * (2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost +
0460                       functor_traits<scalar_quotient_op<T, T> >::Cost) +
0461            functor_traits<scalar_exp_op<T> >::Cost,
0462     PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess
0463   };
0464 };
0465 
0466 template <typename Scalar>
0467 struct scalar_clamp_op {
0468   EIGEN_DEVICE_FUNC inline scalar_clamp_op(const Scalar& _min, const Scalar& _max) : m_min(_min), m_max(_max) {}
0469   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar
0470   operator()(const Scalar& x) const {
0471     return numext::mini(numext::maxi(x, m_min), m_max);
0472   }
0473   template <typename Packet>
0474   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet
0475   packetOp(const Packet& x) const {
0476     return internal::pmin(internal::pmax(x, pset1<Packet>(m_min)), pset1<Packet>(m_max));
0477   }
0478   const Scalar m_min;
0479   const Scalar m_max;
0480 };
0481 template<typename Scalar>
0482 struct functor_traits<scalar_clamp_op<Scalar> >
0483 { enum { Cost = 2 * NumTraits<Scalar>::AddCost, PacketAccess = (packet_traits<Scalar>::HasMin && packet_traits<Scalar>::HasMax)}; };
0484 
0485 } // end namespace internal
0486 } // end namespace Eigen
0487 
0488 #endif // EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H