cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

TensorFunctors.h (15269B)


      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 namespace Eigen {
     14 namespace internal {
     15 
     16 
     17 /** \internal
     18  * \brief Template functor to compute the modulo between an array and a scalar.
     19  */
     20 template <typename Scalar>
     21 struct scalar_mod_op {
     22   EIGEN_DEVICE_FUNC scalar_mod_op(const Scalar& divisor) : m_divisor(divisor) {}
     23   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a % m_divisor; }
     24   const Scalar m_divisor;
     25 };
     26 template <typename Scalar>
     27 struct functor_traits<scalar_mod_op<Scalar> >
     28 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
     29 
     30 
     31 /** \internal
     32  * \brief Template functor to compute the modulo between 2 arrays.
     33  */
     34 template <typename Scalar>
     35 struct scalar_mod2_op {
     36   EIGEN_EMPTY_STRUCT_CTOR(scalar_mod2_op)
     37   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a, const Scalar& b) const { return a % b; }
     38 };
     39 template <typename Scalar>
     40 struct functor_traits<scalar_mod2_op<Scalar> >
     41 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; };
     42 
     43 template <typename Scalar>
     44 struct scalar_fmod_op {
     45   EIGEN_EMPTY_STRUCT_CTOR(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() {
    172     return Eigen::NumTraits<T>::lowest();
    173   }
    174 };
    175 template <typename T>
    176 struct MinMaxBottomValue<T, true, false> {
    177   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
    178     return -Eigen::NumTraits<T>::infinity();
    179   }
    180 };
    181 template <typename T>
    182 struct MinMaxBottomValue<T, false, true> {
    183   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
    184     return Eigen::NumTraits<T>::highest();
    185   }
    186 };
    187 template <typename T>
    188 struct MinMaxBottomValue<T, false, false> {
    189   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() {
    190     return Eigen::NumTraits<T>::infinity();
    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 ArgMaxTupleReducer
    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<ArgMaxTupleReducer<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 ArgMinTupleReducer
    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<ArgMinTupleReducer<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 const 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   {
    435     EIGEN_UNROLL_LOOP
    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);
    443     EIGEN_UNROLL_LOOP
    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