![]() |
Eigen-unsupported
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H 00011 #define EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H 00012 00013 namespace Eigen { 00014 namespace internal { 00015 00016 00020 template <typename Scalar> 00021 struct scalar_mod_op { 00022 EIGEN_DEVICE_FUNC scalar_mod_op(const Scalar& divisor) : m_divisor(divisor) {} 00023 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a % m_divisor; } 00024 const Scalar m_divisor; 00025 }; 00026 template <typename Scalar> 00027 struct functor_traits<scalar_mod_op<Scalar> > 00028 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; }; 00029 00030 00034 template <typename Scalar> 00035 struct scalar_mod2_op { 00036 EIGEN_EMPTY_STRUCT_CTOR(scalar_mod2_op); 00037 EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a, const Scalar& b) const { return a % b; } 00038 }; 00039 template <typename Scalar> 00040 struct functor_traits<scalar_mod2_op<Scalar> > 00041 { enum { Cost = scalar_div_cost<Scalar,false>::value, PacketAccess = false }; }; 00042 00043 template <typename Scalar> 00044 struct scalar_fmod_op { 00045 EIGEN_EMPTY_STRUCT_CTOR(scalar_fmod_op); 00046 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar 00047 operator()(const Scalar& a, const Scalar& b) const { 00048 return numext::fmod(a, b); 00049 } 00050 }; 00051 template <typename Scalar> 00052 struct functor_traits<scalar_fmod_op<Scalar> > { 00053 enum { Cost = 13, // Reciprocal throughput of FPREM on Haswell. 00054 PacketAccess = false }; 00055 }; 00056 00057 00062 template <typename T> 00063 struct scalar_sigmoid_op { 00064 EIGEN_EMPTY_STRUCT_CTOR(scalar_sigmoid_op) 00065 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { 00066 const T one = T(1); 00067 return one / (one + numext::exp(-x)); 00068 } 00069 00070 template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00071 Packet packetOp(const Packet& x) const { 00072 const Packet one = pset1<Packet>(T(1)); 00073 return pdiv(one, padd(one, pexp(pnegate(x)))); 00074 } 00075 }; 00076 00077 template <typename T> 00078 struct functor_traits<scalar_sigmoid_op<T> > { 00079 enum { 00080 Cost = NumTraits<T>::AddCost * 2 + NumTraits<T>::MulCost * 6, 00081 PacketAccess = packet_traits<T>::HasAdd && packet_traits<T>::HasDiv && 00082 packet_traits<T>::HasNegate && packet_traits<T>::HasExp 00083 }; 00084 }; 00085 00086 00087 template<typename Reducer, typename Device> 00088 struct reducer_traits { 00089 enum { 00090 Cost = 1, 00091 PacketAccess = false 00092 }; 00093 }; 00094 00095 // Standard reduction functors 00096 template <typename T> struct SumReducer 00097 { 00098 static const bool PacketAccess = packet_traits<T>::HasAdd; 00099 static const bool IsStateful = false; 00100 00101 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const { 00102 internal::scalar_sum_op<T> sum_op; 00103 *accum = sum_op(*accum, t); 00104 } 00105 template <typename Packet> 00106 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const { 00107 (*accum) = padd<Packet>(*accum, p); 00108 } 00109 00110 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00111 internal::scalar_cast_op<int, T> conv; 00112 return conv(0); 00113 } 00114 template <typename Packet> 00115 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const { 00116 return pset1<Packet>(initialize()); 00117 } 00118 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { 00119 return accum; 00120 } 00121 template <typename Packet> 00122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const { 00123 return vaccum; 00124 } 00125 template <typename Packet> 00126 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const { 00127 internal::scalar_sum_op<T> sum_op; 00128 return sum_op(saccum, predux(vaccum)); 00129 } 00130 }; 00131 00132 template <typename T, typename Device> 00133 struct reducer_traits<SumReducer<T>, Device> { 00134 enum { 00135 Cost = NumTraits<T>::AddCost, 00136 PacketAccess = PacketType<T, Device>::HasAdd 00137 }; 00138 }; 00139 00140 00141 template <typename T> struct MeanReducer 00142 { 00143 static const bool PacketAccess = packet_traits<T>::HasAdd && !NumTraits<T>::IsInteger; 00144 static const bool IsStateful = true; 00145 00146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00147 MeanReducer() : scalarCount_(0), packetCount_(0) { } 00148 00149 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) { 00150 internal::scalar_sum_op<T> sum_op; 00151 *accum = sum_op(*accum, t); 00152 scalarCount_++; 00153 } 00154 template <typename Packet> 00155 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) { 00156 (*accum) = padd<Packet>(*accum, p); 00157 packetCount_++; 00158 } 00159 00160 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00161 internal::scalar_cast_op<int, T> conv; 00162 return conv(0); 00163 } 00164 template <typename Packet> 00165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const { 00166 return pset1<Packet>(initialize()); 00167 } 00168 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { 00169 return accum / scalarCount_; 00170 } 00171 template <typename Packet> 00172 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const { 00173 return pdiv(vaccum, pset1<Packet>(packetCount_)); 00174 } 00175 template <typename Packet> 00176 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const { 00177 internal::scalar_sum_op<T> sum_op; 00178 return sum_op(saccum, predux(vaccum)) / (scalarCount_ + packetCount_ * unpacket_traits<Packet>::size); 00179 } 00180 00181 protected: 00182 DenseIndex scalarCount_; 00183 DenseIndex packetCount_; 00184 }; 00185 00186 template <typename T, typename Device> 00187 struct reducer_traits<MeanReducer<T>, Device> { 00188 enum { 00189 Cost = NumTraits<T>::AddCost, 00190 PacketAccess = PacketType<T, Device>::HasAdd 00191 }; 00192 }; 00193 00194 00195 template <typename T, bool IsMax = true, bool IsInteger = true> 00196 struct MinMaxBottomValue { 00197 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { 00198 return Eigen::NumTraits<T>::lowest(); 00199 } 00200 }; 00201 template <typename T> 00202 struct MinMaxBottomValue<T, true, false> { 00203 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { 00204 return -Eigen::NumTraits<T>::infinity(); 00205 } 00206 }; 00207 template <typename T> 00208 struct MinMaxBottomValue<T, false, true> { 00209 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { 00210 return Eigen::NumTraits<T>::highest(); 00211 } 00212 }; 00213 template <typename T> 00214 struct MinMaxBottomValue<T, false, false> { 00215 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { 00216 return Eigen::NumTraits<T>::infinity(); 00217 } 00218 }; 00219 00220 00221 template <typename T> struct MaxReducer 00222 { 00223 static const bool PacketAccess = packet_traits<T>::HasMax; 00224 static const bool IsStateful = false; 00225 00226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const { 00227 if (t > *accum) { *accum = t; } 00228 } 00229 template <typename Packet> 00230 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const { 00231 (*accum) = pmax<Packet>(*accum, p); 00232 } 00233 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00234 return MinMaxBottomValue<T, true, Eigen::NumTraits<T>::IsInteger>::bottom_value(); 00235 } 00236 template <typename Packet> 00237 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const { 00238 return pset1<Packet>(initialize()); 00239 } 00240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { 00241 return accum; 00242 } 00243 template <typename Packet> 00244 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const { 00245 return vaccum; 00246 } 00247 template <typename Packet> 00248 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const { 00249 return numext::maxi(saccum, predux_max(vaccum)); 00250 } 00251 }; 00252 00253 template <typename T, typename Device> 00254 struct reducer_traits<MaxReducer<T>, Device> { 00255 enum { 00256 Cost = NumTraits<T>::AddCost, 00257 PacketAccess = PacketType<T, Device>::HasMax 00258 }; 00259 }; 00260 00261 00262 template <typename T> struct MinReducer 00263 { 00264 static const bool PacketAccess = packet_traits<T>::HasMin; 00265 static const bool IsStateful = false; 00266 00267 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const { 00268 if (t < *accum) { *accum = t; } 00269 } 00270 template <typename Packet> 00271 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const { 00272 (*accum) = pmin<Packet>(*accum, p); 00273 } 00274 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00275 return MinMaxBottomValue<T, false, Eigen::NumTraits<T>::IsInteger>::bottom_value(); 00276 } 00277 template <typename Packet> 00278 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const { 00279 return pset1<Packet>(initialize()); 00280 } 00281 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { 00282 return accum; 00283 } 00284 template <typename Packet> 00285 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const { 00286 return vaccum; 00287 } 00288 template <typename Packet> 00289 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const { 00290 return numext::mini(saccum, predux_min(vaccum)); 00291 } 00292 }; 00293 00294 template <typename T, typename Device> 00295 struct reducer_traits<MinReducer<T>, Device> { 00296 enum { 00297 Cost = NumTraits<T>::AddCost, 00298 PacketAccess = PacketType<T, Device>::HasMin 00299 }; 00300 }; 00301 00302 00303 template <typename T> struct ProdReducer 00304 { 00305 static const bool PacketAccess = packet_traits<T>::HasMul; 00306 static const bool IsStateful = false; 00307 00308 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const { 00309 internal::scalar_product_op<T> prod_op; 00310 (*accum) = prod_op(*accum, t); 00311 } 00312 template <typename Packet> 00313 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const { 00314 (*accum) = pmul<Packet>(*accum, p); 00315 } 00316 00317 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00318 internal::scalar_cast_op<int, T> conv; 00319 return conv(1); 00320 } 00321 template <typename Packet> 00322 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const { 00323 return pset1<Packet>(initialize()); 00324 } 00325 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { 00326 return accum; 00327 } 00328 template <typename Packet> 00329 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const { 00330 return vaccum; 00331 } 00332 template <typename Packet> 00333 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const { 00334 internal::scalar_product_op<T> prod_op; 00335 return prod_op(saccum, predux_mul(vaccum)); 00336 } 00337 }; 00338 00339 template <typename T, typename Device> 00340 struct reducer_traits<ProdReducer<T>, Device> { 00341 enum { 00342 Cost = NumTraits<T>::MulCost, 00343 PacketAccess = PacketType<T, Device>::HasMul 00344 }; 00345 }; 00346 00347 00348 struct AndReducer 00349 { 00350 static const bool PacketAccess = false; 00351 static const bool IsStateful = false; 00352 00353 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { 00354 *accum = *accum && t; 00355 } 00356 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { 00357 return true; 00358 } 00359 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { 00360 return accum; 00361 } 00362 }; 00363 00364 template <typename Device> 00365 struct reducer_traits<AndReducer, Device> { 00366 enum { 00367 Cost = 1, 00368 PacketAccess = false 00369 }; 00370 }; 00371 00372 00373 struct OrReducer { 00374 static const bool PacketAccess = false; 00375 static const bool IsStateful = false; 00376 00377 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { 00378 *accum = *accum || t; 00379 } 00380 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { 00381 return false; 00382 } 00383 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { 00384 return accum; 00385 } 00386 }; 00387 00388 template <typename Device> 00389 struct reducer_traits<OrReducer, Device> { 00390 enum { 00391 Cost = 1, 00392 PacketAccess = false 00393 }; 00394 }; 00395 00396 00397 // Argmin/Argmax reducers 00398 template <typename T> struct ArgMaxTupleReducer 00399 { 00400 static const bool PacketAccess = false; 00401 static const bool IsStateful = false; 00402 00403 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const { 00404 if (t.second > accum->second) { *accum = t; } 00405 } 00406 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00407 return T(0, NumTraits<typename T::second_type>::lowest()); 00408 } 00409 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { 00410 return accum; 00411 } 00412 }; 00413 00414 template <typename T, typename Device> 00415 struct reducer_traits<ArgMaxTupleReducer<T>, Device> { 00416 enum { 00417 Cost = NumTraits<T>::AddCost, 00418 PacketAccess = false 00419 }; 00420 }; 00421 00422 00423 template <typename T> struct ArgMinTupleReducer 00424 { 00425 static const bool PacketAccess = false; 00426 static const bool IsStateful = false; 00427 00428 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T& t, T* accum) const { 00429 if (t.second < accum->second) { *accum = t; } 00430 } 00431 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const { 00432 return T(0, NumTraits<typename T::second_type>::highest()); 00433 } 00434 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { 00435 return accum; 00436 } 00437 }; 00438 00439 template <typename T, typename Device> 00440 struct reducer_traits<ArgMinTupleReducer<T>, Device> { 00441 enum { 00442 Cost = NumTraits<T>::AddCost, 00443 PacketAccess = false 00444 }; 00445 }; 00446 00447 00448 template <typename T, typename Index, size_t NumDims> 00449 class GaussianGenerator { 00450 public: 00451 static const bool PacketAccess = false; 00452 00453 EIGEN_DEVICE_FUNC GaussianGenerator(const array<T, NumDims>& means, 00454 const array<T, NumDims>& std_devs) 00455 : m_means(means) 00456 { 00457 for (size_t i = 0; i < NumDims; ++i) { 00458 m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2; 00459 } 00460 } 00461 00462 EIGEN_DEVICE_FUNC T operator()(const array<Index, NumDims>& coordinates) const { 00463 T tmp = T(0); 00464 for (size_t i = 0; i < NumDims; ++i) { 00465 T offset = coordinates[i] - m_means[i]; 00466 tmp += offset * offset / m_two_sigmas[i]; 00467 } 00468 return numext::exp(-tmp); 00469 } 00470 00471 private: 00472 array<T, NumDims> m_means; 00473 array<T, NumDims> m_two_sigmas; 00474 }; 00475 00476 template <typename T, typename Index, size_t NumDims> 00477 struct functor_traits<GaussianGenerator<T, Index, NumDims> > { 00478 enum { 00479 Cost = NumDims * (2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost + 00480 functor_traits<scalar_quotient_op<T, T> >::Cost) + 00481 functor_traits<scalar_exp_op<T> >::Cost, 00482 PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess 00483 }; 00484 }; 00485 00486 } // end namespace internal 00487 } // end namespace Eigen 00488 00489 #endif // EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H