cart-elc

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

GenericPacketMath.h (38812B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
      5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_GENERIC_PACKET_MATH_H
     12 #define EIGEN_GENERIC_PACKET_MATH_H
     13 
     14 namespace Eigen {
     15 
     16 namespace internal {
     17 
     18 /** \internal
     19   * \file GenericPacketMath.h
     20   *
     21   * Default implementation for types not supported by the vectorization.
     22   * In practice these functions are provided to make easier the writing
     23   * of generic vectorized code.
     24   */
     25 
     26 #ifndef EIGEN_DEBUG_ALIGNED_LOAD
     27 #define EIGEN_DEBUG_ALIGNED_LOAD
     28 #endif
     29 
     30 #ifndef EIGEN_DEBUG_UNALIGNED_LOAD
     31 #define EIGEN_DEBUG_UNALIGNED_LOAD
     32 #endif
     33 
     34 #ifndef EIGEN_DEBUG_ALIGNED_STORE
     35 #define EIGEN_DEBUG_ALIGNED_STORE
     36 #endif
     37 
     38 #ifndef EIGEN_DEBUG_UNALIGNED_STORE
     39 #define EIGEN_DEBUG_UNALIGNED_STORE
     40 #endif
     41 
     42 struct default_packet_traits
     43 {
     44   enum {
     45     HasHalfPacket = 0,
     46 
     47     HasAdd       = 1,
     48     HasSub       = 1,
     49     HasShift     = 1,
     50     HasMul       = 1,
     51     HasNegate    = 1,
     52     HasAbs       = 1,
     53     HasArg       = 0,
     54     HasAbs2      = 1,
     55     HasAbsDiff   = 0,
     56     HasMin       = 1,
     57     HasMax       = 1,
     58     HasConj      = 1,
     59     HasSetLinear = 1,
     60     HasBlend     = 0,
     61     // This flag is used to indicate whether packet comparison is supported.
     62     // pcmp_eq, pcmp_lt and pcmp_le should be defined for it to be true.
     63     HasCmp       = 0,
     64 
     65     HasDiv    = 0,
     66     HasSqrt   = 0,
     67     HasRsqrt  = 0,
     68     HasExp    = 0,
     69     HasExpm1  = 0,
     70     HasLog    = 0,
     71     HasLog1p  = 0,
     72     HasLog10  = 0,
     73     HasPow    = 0,
     74 
     75     HasSin    = 0,
     76     HasCos    = 0,
     77     HasTan    = 0,
     78     HasASin   = 0,
     79     HasACos   = 0,
     80     HasATan   = 0,
     81     HasSinh   = 0,
     82     HasCosh   = 0,
     83     HasTanh   = 0,
     84     HasLGamma = 0,
     85     HasDiGamma = 0,
     86     HasZeta = 0,
     87     HasPolygamma = 0,
     88     HasErf = 0,
     89     HasErfc = 0,
     90     HasNdtri = 0,
     91     HasBessel = 0,
     92     HasIGamma = 0,
     93     HasIGammaDerA = 0,
     94     HasGammaSampleDerAlpha = 0,
     95     HasIGammac = 0,
     96     HasBetaInc = 0,
     97 
     98     HasRound  = 0,
     99     HasRint   = 0,
    100     HasFloor  = 0,
    101     HasCeil   = 0,
    102     HasSign   = 0
    103   };
    104 };
    105 
    106 template<typename T> struct packet_traits : default_packet_traits
    107 {
    108   typedef T type;
    109   typedef T half;
    110   enum {
    111     Vectorizable = 0,
    112     size = 1,
    113     AlignedOnScalar = 0,
    114     HasHalfPacket = 0
    115   };
    116   enum {
    117     HasAdd    = 0,
    118     HasSub    = 0,
    119     HasMul    = 0,
    120     HasNegate = 0,
    121     HasAbs    = 0,
    122     HasAbs2   = 0,
    123     HasMin    = 0,
    124     HasMax    = 0,
    125     HasConj   = 0,
    126     HasSetLinear = 0
    127   };
    128 };
    129 
    130 template<typename T> struct packet_traits<const T> : packet_traits<T> { };
    131 
    132 template<typename T> struct unpacket_traits
    133 {
    134   typedef T type;
    135   typedef T half;
    136   enum
    137   {
    138     size = 1,
    139     alignment = 1,
    140     vectorizable = false,
    141     masked_load_available=false,
    142     masked_store_available=false
    143   };
    144 };
    145 
    146 template<typename T> struct unpacket_traits<const T> : unpacket_traits<T> { };
    147 
    148 template <typename Src, typename Tgt> struct type_casting_traits {
    149   enum {
    150     VectorizedCast = 0,
    151     SrcCoeffRatio = 1,
    152     TgtCoeffRatio = 1
    153   };
    154 };
    155 
    156 /** \internal Wrapper to ensure that multiple packet types can map to the same
    157     same underlying vector type. */
    158 template<typename T, int unique_id = 0>
    159 struct eigen_packet_wrapper
    160 {
    161   EIGEN_ALWAYS_INLINE operator T&() { return m_val; }
    162   EIGEN_ALWAYS_INLINE operator const T&() const { return m_val; }
    163   EIGEN_ALWAYS_INLINE eigen_packet_wrapper() {}
    164   EIGEN_ALWAYS_INLINE eigen_packet_wrapper(const T &v) : m_val(v) {}
    165   EIGEN_ALWAYS_INLINE eigen_packet_wrapper& operator=(const T &v) {
    166     m_val = v;
    167     return *this;
    168   }
    169 
    170   T m_val;
    171 };
    172 
    173 
    174 /** \internal A convenience utility for determining if the type is a scalar.
    175  * This is used to enable some generic packet implementations.
    176  */
    177 template<typename Packet>
    178 struct is_scalar {
    179   typedef typename unpacket_traits<Packet>::type Scalar;
    180   enum {
    181     value = internal::is_same<Packet, Scalar>::value
    182   };
    183 };
    184 
    185 /** \internal \returns static_cast<TgtType>(a) (coeff-wise) */
    186 template <typename SrcPacket, typename TgtPacket>
    187 EIGEN_DEVICE_FUNC inline TgtPacket
    188 pcast(const SrcPacket& a) {
    189   return static_cast<TgtPacket>(a);
    190 }
    191 template <typename SrcPacket, typename TgtPacket>
    192 EIGEN_DEVICE_FUNC inline TgtPacket
    193 pcast(const SrcPacket& a, const SrcPacket& /*b*/) {
    194   return static_cast<TgtPacket>(a);
    195 }
    196 template <typename SrcPacket, typename TgtPacket>
    197 EIGEN_DEVICE_FUNC inline TgtPacket
    198 pcast(const SrcPacket& a, const SrcPacket& /*b*/, const SrcPacket& /*c*/, const SrcPacket& /*d*/) {
    199   return static_cast<TgtPacket>(a);
    200 }
    201 template <typename SrcPacket, typename TgtPacket>
    202 EIGEN_DEVICE_FUNC inline TgtPacket
    203 pcast(const SrcPacket& a, const SrcPacket& /*b*/, const SrcPacket& /*c*/, const SrcPacket& /*d*/,
    204       const SrcPacket& /*e*/, const SrcPacket& /*f*/, const SrcPacket& /*g*/, const SrcPacket& /*h*/) {
    205   return static_cast<TgtPacket>(a);
    206 }
    207 
    208 /** \internal \returns reinterpret_cast<Target>(a) */
    209 template <typename Target, typename Packet>
    210 EIGEN_DEVICE_FUNC inline Target
    211 preinterpret(const Packet& a); /* { return reinterpret_cast<const Target&>(a); } */
    212 
    213 /** \internal \returns a + b (coeff-wise) */
    214 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    215 padd(const Packet& a, const Packet& b) { return a+b; }
    216 // Avoid compiler warning for boolean algebra.
    217 template<> EIGEN_DEVICE_FUNC inline bool
    218 padd(const bool& a, const bool& b) { return a || b; }
    219 
    220 /** \internal \returns a - b (coeff-wise) */
    221 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    222 psub(const Packet& a, const Packet& b) { return a-b; }
    223 
    224 /** \internal \returns -a (coeff-wise) */
    225 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    226 pnegate(const Packet& a) { return -a; }
    227 
    228 template<> EIGEN_DEVICE_FUNC inline bool
    229 pnegate(const bool& a) { return !a; }
    230 
    231 /** \internal \returns conj(a) (coeff-wise) */
    232 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    233 pconj(const Packet& a) { return numext::conj(a); }
    234 
    235 /** \internal \returns a * b (coeff-wise) */
    236 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    237 pmul(const Packet& a, const Packet& b) { return a*b; }
    238 // Avoid compiler warning for boolean algebra.
    239 template<> EIGEN_DEVICE_FUNC inline bool
    240 pmul(const bool& a, const bool& b) { return a && b; }
    241 
    242 /** \internal \returns a / b (coeff-wise) */
    243 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    244 pdiv(const Packet& a, const Packet& b) { return a/b; }
    245 
    246 // In the generic case, memset to all one bits.
    247 template<typename Packet, typename EnableIf = void>
    248 struct ptrue_impl {
    249   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/){
    250     Packet b;
    251     memset(static_cast<void*>(&b), 0xff, sizeof(Packet));
    252     return b;
    253   }
    254 };
    255 
    256 // For non-trivial scalars, set to Scalar(1) (i.e. a non-zero value).
    257 // Although this is technically not a valid bitmask, the scalar path for pselect
    258 // uses a comparison to zero, so this should still work in most cases. We don't
    259 // have another option, since the scalar type requires initialization.
    260 template<typename T>
    261 struct ptrue_impl<T, 
    262     typename internal::enable_if<is_scalar<T>::value && NumTraits<T>::RequireInitialization>::type > {
    263   static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/){
    264     return T(1);
    265   }
    266 };
    267 
    268 /** \internal \returns one bits. */
    269 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    270 ptrue(const Packet& a) {
    271   return ptrue_impl<Packet>::run(a);
    272 }
    273 
    274 // In the general case, memset to zero.
    275 template<typename Packet, typename EnableIf = void>
    276 struct pzero_impl {
    277   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& /*a*/) {
    278     Packet b;
    279     memset(static_cast<void*>(&b), 0x00, sizeof(Packet));
    280     return b;
    281   }
    282 };
    283 
    284 // For scalars, explicitly set to Scalar(0), since the underlying representation
    285 // for zero may not consist of all-zero bits.
    286 template<typename T>
    287 struct pzero_impl<T,
    288     typename internal::enable_if<is_scalar<T>::value>::type> {
    289   static EIGEN_DEVICE_FUNC inline T run(const T& /*a*/) {
    290     return T(0);
    291   }
    292 };
    293 
    294 /** \internal \returns packet of zeros */
    295 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    296 pzero(const Packet& a) {
    297   return pzero_impl<Packet>::run(a);
    298 }
    299 
    300 /** \internal \returns a <= b as a bit mask */
    301 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    302 pcmp_le(const Packet& a, const Packet& b)  { return a<=b ? ptrue(a) : pzero(a); }
    303 
    304 /** \internal \returns a < b as a bit mask */
    305 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    306 pcmp_lt(const Packet& a, const Packet& b)  { return a<b ? ptrue(a) : pzero(a); }
    307 
    308 /** \internal \returns a == b as a bit mask */
    309 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    310 pcmp_eq(const Packet& a, const Packet& b) { return a==b ? ptrue(a) : pzero(a); }
    311 
    312 /** \internal \returns a < b or a==NaN or b==NaN as a bit mask */
    313 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    314 pcmp_lt_or_nan(const Packet& a, const Packet& b) { return a>=b ? pzero(a) : ptrue(a); }
    315 
    316 template<typename T>
    317 struct bit_and {
    318   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
    319     return a & b;
    320   }
    321 };
    322 
    323 template<typename T>
    324 struct bit_or {
    325   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
    326     return a | b;
    327   }
    328 };
    329 
    330 template<typename T>
    331 struct bit_xor {
    332   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a, const T& b) const {
    333     return a ^ b;
    334   }
    335 };
    336 
    337 template<typename T>
    338 struct bit_not {
    339   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR EIGEN_ALWAYS_INLINE T operator()(const T& a) const {
    340     return ~a;
    341   }
    342 };
    343 
    344 // Use operators &, |, ^, ~.
    345 template<typename T>
    346 struct operator_bitwise_helper {
    347   EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) { return bit_and<T>()(a, b); }
    348   EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { return bit_or<T>()(a, b); }
    349   EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) { return bit_xor<T>()(a, b); }
    350   EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { return bit_not<T>()(a); }
    351 };
    352 
    353 // Apply binary operations byte-by-byte
    354 template<typename T>
    355 struct bytewise_bitwise_helper {
    356   EIGEN_DEVICE_FUNC static inline T bitwise_and(const T& a, const T& b) {
    357     return binary(a, b, bit_and<unsigned char>());
    358   }
    359   EIGEN_DEVICE_FUNC static inline T bitwise_or(const T& a, const T& b) { 
    360     return binary(a, b, bit_or<unsigned char>());
    361    }
    362   EIGEN_DEVICE_FUNC static inline T bitwise_xor(const T& a, const T& b) {
    363     return binary(a, b, bit_xor<unsigned char>());
    364   }
    365   EIGEN_DEVICE_FUNC static inline T bitwise_not(const T& a) { 
    366     return unary(a,bit_not<unsigned char>());
    367    }
    368   
    369  private:
    370   template<typename Op>
    371   EIGEN_DEVICE_FUNC static inline T unary(const T& a, Op op) {
    372     const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
    373     T c;
    374     unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
    375     for (size_t i = 0; i < sizeof(T); ++i) {
    376       *c_ptr++ = op(*a_ptr++);
    377     }
    378     return c;
    379   }
    380 
    381   template<typename Op>
    382   EIGEN_DEVICE_FUNC static inline T binary(const T& a, const T& b, Op op) {
    383     const unsigned char* a_ptr = reinterpret_cast<const unsigned char*>(&a);
    384     const unsigned char* b_ptr = reinterpret_cast<const unsigned char*>(&b);
    385     T c;
    386     unsigned char* c_ptr = reinterpret_cast<unsigned char*>(&c);
    387     for (size_t i = 0; i < sizeof(T); ++i) {
    388       *c_ptr++ = op(*a_ptr++, *b_ptr++);
    389     }
    390     return c;
    391   }
    392 };
    393 
    394 // In the general case, use byte-by-byte manipulation.
    395 template<typename T, typename EnableIf = void>
    396 struct bitwise_helper : public bytewise_bitwise_helper<T> {};
    397 
    398 // For integers or non-trivial scalars, use binary operators.
    399 template<typename T>
    400 struct bitwise_helper<T,
    401   typename internal::enable_if<
    402     is_scalar<T>::value && (NumTraits<T>::IsInteger || NumTraits<T>::RequireInitialization)>::type
    403   > : public operator_bitwise_helper<T> {};
    404 
    405 /** \internal \returns the bitwise and of \a a and \a b */
    406 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    407 pand(const Packet& a, const Packet& b) {
    408   return bitwise_helper<Packet>::bitwise_and(a, b);
    409 }
    410 
    411 /** \internal \returns the bitwise or of \a a and \a b */
    412 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    413 por(const Packet& a, const Packet& b) {
    414   return bitwise_helper<Packet>::bitwise_or(a, b);
    415 }
    416 
    417 /** \internal \returns the bitwise xor of \a a and \a b */
    418 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    419 pxor(const Packet& a, const Packet& b) {
    420   return bitwise_helper<Packet>::bitwise_xor(a, b);
    421 }
    422 
    423 /** \internal \returns the bitwise not of \a a */
    424 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    425 pnot(const Packet& a) {
    426   return bitwise_helper<Packet>::bitwise_not(a);
    427 }
    428 
    429 /** \internal \returns the bitwise and of \a a and not \a b */
    430 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    431 pandnot(const Packet& a, const Packet& b) { return pand(a, pnot(b)); }
    432 
    433 // In the general case, use bitwise select.
    434 template<typename Packet, typename EnableIf = void>
    435 struct pselect_impl {
    436   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
    437     return por(pand(a,mask),pandnot(b,mask));
    438   }
    439 };
    440 
    441 // For scalars, use ternary select.
    442 template<typename Packet>
    443 struct pselect_impl<Packet, 
    444     typename internal::enable_if<is_scalar<Packet>::value>::type > {
    445   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& mask, const Packet& a, const Packet& b) {
    446     return numext::equal_strict(mask, Packet(0)) ? b : a;
    447   }
    448 };
    449 
    450 /** \internal \returns \a or \b for each field in packet according to \mask */
    451 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    452 pselect(const Packet& mask, const Packet& a, const Packet& b) {
    453   return pselect_impl<Packet>::run(mask, a, b);
    454 }
    455 
    456 template<> EIGEN_DEVICE_FUNC inline bool pselect<bool>(
    457     const bool& cond, const bool& a, const bool& b) {
    458   return cond ? a : b;
    459 }
    460 
    461 /** \internal \returns the min or of \a a and \a b (coeff-wise)
    462     If either \a a or \a b are NaN, the result is implementation defined. */
    463 template<int NaNPropagation>
    464 struct pminmax_impl {
    465   template <typename Packet, typename Op>
    466   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
    467     return op(a,b);
    468   }
    469 };
    470 
    471 /** \internal \returns the min or max of \a a and \a b (coeff-wise)
    472     If either \a a or \a b are NaN, NaN is returned. */
    473 template<>
    474 struct pminmax_impl<PropagateNaN> {
    475   template <typename Packet, typename Op>
    476   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
    477   Packet not_nan_mask_a = pcmp_eq(a, a);
    478   Packet not_nan_mask_b = pcmp_eq(b, b);
    479   return pselect(not_nan_mask_a,
    480                  pselect(not_nan_mask_b, op(a, b), b),
    481                  a);
    482   }
    483 };
    484 
    485 /** \internal \returns the min or max of \a a and \a b (coeff-wise)
    486     If both \a a and \a b are NaN, NaN is returned.
    487     Equivalent to std::fmin(a, b).  */
    488 template<>
    489 struct pminmax_impl<PropagateNumbers> {
    490   template <typename Packet, typename Op>
    491   static EIGEN_DEVICE_FUNC inline Packet run(const Packet& a, const Packet& b, Op op) {
    492   Packet not_nan_mask_a = pcmp_eq(a, a);
    493   Packet not_nan_mask_b = pcmp_eq(b, b);
    494   return pselect(not_nan_mask_a,
    495                  pselect(not_nan_mask_b, op(a, b), a),
    496                  b);
    497   }
    498 };
    499 
    500 
    501 #ifndef SYCL_DEVICE_ONLY
    502 #define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) Func
    503 #else
    504 #define EIGEN_BINARY_OP_NAN_PROPAGATION(Type, Func) \
    505 [](const Type& a, const Type& b) { \
    506         return Func(a, b);}
    507 #endif
    508 
    509 /** \internal \returns the min of \a a and \a b  (coeff-wise).
    510     If \a a or \b b is NaN, the return value is implementation defined. */
    511 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    512 pmin(const Packet& a, const Packet& b) { return numext::mini(a,b); }
    513 
    514 /** \internal \returns the min of \a a and \a b  (coeff-wise).
    515     NaNPropagation determines the NaN propagation semantics. */
    516 template <int NaNPropagation, typename Packet>
    517 EIGEN_DEVICE_FUNC inline Packet pmin(const Packet& a, const Packet& b) {
    518   return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet, (pmin<Packet>)));
    519 }
    520 
    521 /** \internal \returns the max of \a a and \a b  (coeff-wise)
    522     If \a a or \b b is NaN, the return value is implementation defined. */
    523 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    524 pmax(const Packet& a, const Packet& b) { return numext::maxi(a, b); }
    525 
    526 /** \internal \returns the max of \a a and \a b  (coeff-wise).
    527     NaNPropagation determines the NaN propagation semantics. */
    528 template <int NaNPropagation, typename Packet>
    529 EIGEN_DEVICE_FUNC inline Packet pmax(const Packet& a, const Packet& b) {
    530   return pminmax_impl<NaNPropagation>::run(a, b, EIGEN_BINARY_OP_NAN_PROPAGATION(Packet,(pmax<Packet>)));
    531 }
    532 
    533 /** \internal \returns the absolute value of \a a */
    534 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    535 pabs(const Packet& a) { return numext::abs(a); }
    536 template<> EIGEN_DEVICE_FUNC inline unsigned int
    537 pabs(const unsigned int& a) { return a; }
    538 template<> EIGEN_DEVICE_FUNC inline unsigned long
    539 pabs(const unsigned long& a) { return a; }
    540 template<> EIGEN_DEVICE_FUNC inline unsigned long long
    541 pabs(const unsigned long long& a) { return a; }
    542 
    543 /** \internal \returns the addsub value of \a a,b */
    544 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    545 paddsub(const Packet& a, const Packet& b) {
    546   return pselect(peven_mask(a), padd(a, b), psub(a, b));
    547  }
    548 
    549 /** \internal \returns the phase angle of \a a */
    550 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    551 parg(const Packet& a) { using numext::arg; return arg(a); }
    552 
    553 
    554 /** \internal \returns \a a logically shifted by N bits to the right */
    555 template<int N> EIGEN_DEVICE_FUNC inline int
    556 parithmetic_shift_right(const int& a) { return a >> N; }
    557 template<int N> EIGEN_DEVICE_FUNC inline long int
    558 parithmetic_shift_right(const long int& a) { return a >> N; }
    559 
    560 /** \internal \returns \a a arithmetically shifted by N bits to the right */
    561 template<int N> EIGEN_DEVICE_FUNC inline int
    562 plogical_shift_right(const int& a) { return static_cast<int>(static_cast<unsigned int>(a) >> N); }
    563 template<int N> EIGEN_DEVICE_FUNC inline long int
    564 plogical_shift_right(const long int& a) { return static_cast<long>(static_cast<unsigned long>(a) >> N); }
    565 
    566 /** \internal \returns \a a shifted by N bits to the left */
    567 template<int N> EIGEN_DEVICE_FUNC inline int
    568 plogical_shift_left(const int& a) { return a << N; }
    569 template<int N> EIGEN_DEVICE_FUNC inline long int
    570 plogical_shift_left(const long int& a) { return a << N; }
    571 
    572 /** \internal \returns the significant and exponent of the underlying floating point numbers
    573   * See https://en.cppreference.com/w/cpp/numeric/math/frexp
    574   */
    575 template <typename Packet>
    576 EIGEN_DEVICE_FUNC inline Packet pfrexp(const Packet& a, Packet& exponent) {
    577   int exp;
    578   EIGEN_USING_STD(frexp);
    579   Packet result = static_cast<Packet>(frexp(a, &exp));
    580   exponent = static_cast<Packet>(exp);
    581   return result;
    582 }
    583 
    584 /** \internal \returns a * 2^((int)exponent)
    585   * See https://en.cppreference.com/w/cpp/numeric/math/ldexp
    586   */
    587 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    588 pldexp(const Packet &a, const Packet &exponent) {
    589   EIGEN_USING_STD(ldexp)
    590   return static_cast<Packet>(ldexp(a, static_cast<int>(exponent)));
    591 }
    592 
    593 /** \internal \returns the min of \a a and \a b  (coeff-wise) */
    594 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    595 pabsdiff(const Packet& a, const Packet& b) { return pselect(pcmp_lt(a, b), psub(b, a), psub(a, b)); }
    596 
    597 /** \internal \returns a packet version of \a *from, from must be 16 bytes aligned */
    598 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    599 pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
    600 
    601 /** \internal \returns a packet version of \a *from, (un-aligned load) */
    602 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    603 ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
    604 
    605 /** \internal \returns a packet version of \a *from, (un-aligned masked load)
    606  * There is no generic implementation. We only have implementations for specialized
    607  * cases. Generic case should not be called.
    608  */
    609 template<typename Packet> EIGEN_DEVICE_FUNC inline
    610 typename enable_if<unpacket_traits<Packet>::masked_load_available, Packet>::type
    611 ploadu(const typename unpacket_traits<Packet>::type* from, typename unpacket_traits<Packet>::mask_t umask);
    612 
    613 /** \internal \returns a packet with constant coefficients \a a, e.g.: (a,a,a,a) */
    614 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    615 pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
    616 
    617 /** \internal \returns a packet with constant coefficients set from bits */
    618 template<typename Packet,typename BitsType> EIGEN_DEVICE_FUNC inline Packet
    619 pset1frombits(BitsType a);
    620 
    621 /** \internal \returns a packet with constant coefficients \a a[0], e.g.: (a[0],a[0],a[0],a[0]) */
    622 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    623 pload1(const typename unpacket_traits<Packet>::type  *a) { return pset1<Packet>(*a); }
    624 
    625 /** \internal \returns a packet with elements of \a *from duplicated.
    626   * For instance, for a packet of 8 elements, 4 scalars will be read from \a *from and
    627   * duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]}
    628   * Currently, this function is only used for scalar * complex products.
    629   */
    630 template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet
    631 ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
    632 
    633 /** \internal \returns a packet with elements of \a *from quadrupled.
    634   * For instance, for a packet of 8 elements, 2 scalars will be read from \a *from and
    635   * replicated to form: {from[0],from[0],from[0],from[0],from[1],from[1],from[1],from[1]}
    636   * Currently, this function is only used in matrix products.
    637   * For packet-size smaller or equal to 4, this function is equivalent to pload1
    638   */
    639 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    640 ploadquad(const typename unpacket_traits<Packet>::type* from)
    641 { return pload1<Packet>(from); }
    642 
    643 /** \internal equivalent to
    644   * \code
    645   * a0 = pload1(a+0);
    646   * a1 = pload1(a+1);
    647   * a2 = pload1(a+2);
    648   * a3 = pload1(a+3);
    649   * \endcode
    650   * \sa pset1, pload1, ploaddup, pbroadcast2
    651   */
    652 template<typename Packet> EIGEN_DEVICE_FUNC
    653 inline void pbroadcast4(const typename unpacket_traits<Packet>::type *a,
    654                         Packet& a0, Packet& a1, Packet& a2, Packet& a3)
    655 {
    656   a0 = pload1<Packet>(a+0);
    657   a1 = pload1<Packet>(a+1);
    658   a2 = pload1<Packet>(a+2);
    659   a3 = pload1<Packet>(a+3);
    660 }
    661 
    662 /** \internal equivalent to
    663   * \code
    664   * a0 = pload1(a+0);
    665   * a1 = pload1(a+1);
    666   * \endcode
    667   * \sa pset1, pload1, ploaddup, pbroadcast4
    668   */
    669 template<typename Packet> EIGEN_DEVICE_FUNC
    670 inline void pbroadcast2(const typename unpacket_traits<Packet>::type *a,
    671                         Packet& a0, Packet& a1)
    672 {
    673   a0 = pload1<Packet>(a+0);
    674   a1 = pload1<Packet>(a+1);
    675 }
    676 
    677 /** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */
    678 template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet
    679 plset(const typename unpacket_traits<Packet>::type& a) { return a; }
    680 
    681 /** \internal \returns a packet with constant coefficients \a a, e.g.: (x, 0, x, 0),
    682      where x is the value of all 1-bits. */
    683 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    684 peven_mask(const Packet& /*a*/) {
    685   typedef typename unpacket_traits<Packet>::type Scalar;
    686   const size_t n = unpacket_traits<Packet>::size;
    687   EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
    688   for(size_t i = 0; i < n; ++i) {
    689     memset(elements+i, ((i & 1) == 0 ? 0xff : 0), sizeof(Scalar));
    690   }
    691   return ploadu<Packet>(elements);
    692 }
    693 
    694 
    695 /** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */
    696 template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstore(Scalar* to, const Packet& from)
    697 { (*to) = from; }
    698 
    699 /** \internal copy the packet \a from to \a *to, (un-aligned store) */
    700 template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pstoreu(Scalar* to, const Packet& from)
    701 {  (*to) = from; }
    702 
    703 /** \internal copy the packet \a from to \a *to, (un-aligned store with a mask)
    704  * There is no generic implementation. We only have implementations for specialized
    705  * cases. Generic case should not be called.
    706  */
    707 template<typename Scalar, typename Packet>
    708 EIGEN_DEVICE_FUNC inline
    709 typename enable_if<unpacket_traits<Packet>::masked_store_available, void>::type
    710 pstoreu(Scalar* to, const Packet& from, typename unpacket_traits<Packet>::mask_t umask);
    711 
    712  template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline Packet pgather(const Scalar* from, Index /*stride*/)
    713  { return ploadu<Packet>(from); }
    714 
    715  template<typename Scalar, typename Packet> EIGEN_DEVICE_FUNC inline void pscatter(Scalar* to, const Packet& from, Index /*stride*/)
    716  { pstore(to, from); }
    717 
    718 /** \internal tries to do cache prefetching of \a addr */
    719 template<typename Scalar> EIGEN_DEVICE_FUNC inline void prefetch(const Scalar* addr)
    720 {
    721 #if defined(EIGEN_HIP_DEVICE_COMPILE)
    722   // do nothing
    723 #elif defined(EIGEN_CUDA_ARCH)
    724 #if defined(__LP64__) || EIGEN_OS_WIN64
    725   // 64-bit pointer operand constraint for inlined asm
    726   asm(" prefetch.L1 [ %1 ];" : "=l"(addr) : "l"(addr));
    727 #else
    728   // 32-bit pointer operand constraint for inlined asm
    729   asm(" prefetch.L1 [ %1 ];" : "=r"(addr) : "r"(addr));
    730 #endif
    731 #elif (!EIGEN_COMP_MSVC) && (EIGEN_COMP_GNUC || EIGEN_COMP_CLANG || EIGEN_COMP_ICC)
    732   __builtin_prefetch(addr);
    733 #endif
    734 }
    735 
    736 /** \internal \returns the reversed elements of \a a*/
    737 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet preverse(const Packet& a)
    738 { return a; }
    739 
    740 /** \internal \returns \a a with real and imaginary part flipped (for complex type only) */
    741 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet pcplxflip(const Packet& a)
    742 {
    743   return Packet(numext::imag(a),numext::real(a));
    744 }
    745 
    746 /**************************
    747 * Special math functions
    748 ***************************/
    749 
    750 /** \internal \returns the sine of \a a (coeff-wise) */
    751 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    752 Packet psin(const Packet& a) { EIGEN_USING_STD(sin); return sin(a); }
    753 
    754 /** \internal \returns the cosine of \a a (coeff-wise) */
    755 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    756 Packet pcos(const Packet& a) { EIGEN_USING_STD(cos); return cos(a); }
    757 
    758 /** \internal \returns the tan of \a a (coeff-wise) */
    759 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    760 Packet ptan(const Packet& a) { EIGEN_USING_STD(tan); return tan(a); }
    761 
    762 /** \internal \returns the arc sine of \a a (coeff-wise) */
    763 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    764 Packet pasin(const Packet& a) { EIGEN_USING_STD(asin); return asin(a); }
    765 
    766 /** \internal \returns the arc cosine of \a a (coeff-wise) */
    767 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    768 Packet pacos(const Packet& a) { EIGEN_USING_STD(acos); return acos(a); }
    769 
    770 /** \internal \returns the arc tangent of \a a (coeff-wise) */
    771 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    772 Packet patan(const Packet& a) { EIGEN_USING_STD(atan); return atan(a); }
    773 
    774 /** \internal \returns the hyperbolic sine of \a a (coeff-wise) */
    775 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    776 Packet psinh(const Packet& a) { EIGEN_USING_STD(sinh); return sinh(a); }
    777 
    778 /** \internal \returns the hyperbolic cosine of \a a (coeff-wise) */
    779 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    780 Packet pcosh(const Packet& a) { EIGEN_USING_STD(cosh); return cosh(a); }
    781 
    782 /** \internal \returns the hyperbolic tan of \a a (coeff-wise) */
    783 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    784 Packet ptanh(const Packet& a) { EIGEN_USING_STD(tanh); return tanh(a); }
    785 
    786 /** \internal \returns the exp of \a a (coeff-wise) */
    787 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    788 Packet pexp(const Packet& a) { EIGEN_USING_STD(exp); return exp(a); }
    789 
    790 /** \internal \returns the expm1 of \a a (coeff-wise) */
    791 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    792 Packet pexpm1(const Packet& a) { return numext::expm1(a); }
    793 
    794 /** \internal \returns the log of \a a (coeff-wise) */
    795 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    796 Packet plog(const Packet& a) { EIGEN_USING_STD(log); return log(a); }
    797 
    798 /** \internal \returns the log1p of \a a (coeff-wise) */
    799 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    800 Packet plog1p(const Packet& a) { return numext::log1p(a); }
    801 
    802 /** \internal \returns the log10 of \a a (coeff-wise) */
    803 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    804 Packet plog10(const Packet& a) { EIGEN_USING_STD(log10); return log10(a); }
    805 
    806 /** \internal \returns the log10 of \a a (coeff-wise) */
    807 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    808 Packet plog2(const Packet& a) {
    809   typedef typename internal::unpacket_traits<Packet>::type Scalar;
    810   return pmul(pset1<Packet>(Scalar(EIGEN_LOG2E)), plog(a)); 
    811 }
    812 
    813 /** \internal \returns the square-root of \a a (coeff-wise) */
    814 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    815 Packet psqrt(const Packet& a) { return numext::sqrt(a); }
    816 
    817 /** \internal \returns the reciprocal square-root of \a a (coeff-wise) */
    818 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    819 Packet prsqrt(const Packet& a) {
    820   typedef typename internal::unpacket_traits<Packet>::type Scalar;
    821   return pdiv(pset1<Packet>(Scalar(1)), psqrt(a));
    822 }
    823 
    824 /** \internal \returns the rounded value of \a a (coeff-wise) */
    825 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    826 Packet pround(const Packet& a) { using numext::round; return round(a); }
    827 
    828 /** \internal \returns the floor of \a a (coeff-wise) */
    829 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    830 Packet pfloor(const Packet& a) { using numext::floor; return floor(a); }
    831 
    832 /** \internal \returns the rounded value of \a a (coeff-wise) with current
    833  * rounding mode */
    834 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    835 Packet print(const Packet& a) { using numext::rint; return rint(a); }
    836 
    837 /** \internal \returns the ceil of \a a (coeff-wise) */
    838 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
    839 Packet pceil(const Packet& a) { using numext::ceil; return ceil(a); }
    840 
    841 /** \internal \returns the first element of a packet */
    842 template<typename Packet>
    843 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type
    844 pfirst(const Packet& a)
    845 { return a; }
    846 
    847 /** \internal \returns the sum of the elements of upper and lower half of \a a if \a a is larger than 4.
    848   * For a packet {a0, a1, a2, a3, a4, a5, a6, a7}, it returns a half packet {a0+a4, a1+a5, a2+a6, a3+a7}
    849   * For packet-size smaller or equal to 4, this boils down to a noop.
    850   */
    851 template<typename Packet>
    852 EIGEN_DEVICE_FUNC inline typename conditional<(unpacket_traits<Packet>::size%8)==0,typename unpacket_traits<Packet>::half,Packet>::type
    853 predux_half_dowto4(const Packet& a)
    854 { return a; }
    855 
    856 // Slow generic implementation of Packet reduction.
    857 template <typename Packet, typename Op>
    858 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type
    859 predux_helper(const Packet& a, Op op) {
    860   typedef typename unpacket_traits<Packet>::type Scalar;
    861   const size_t n = unpacket_traits<Packet>::size;
    862   EIGEN_ALIGN_TO_BOUNDARY(sizeof(Packet)) Scalar elements[n];
    863   pstoreu<Scalar>(elements, a);
    864   for(size_t k = n / 2; k > 0; k /= 2)  {
    865     for(size_t i = 0; i < k; ++i) {
    866       elements[i] = op(elements[i], elements[i + k]);
    867     }
    868   }
    869   return elements[0];
    870 }
    871 
    872 /** \internal \returns the sum of the elements of \a a*/
    873 template<typename Packet>
    874 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type
    875 predux(const Packet& a)
    876 {
    877   return a;
    878 }
    879 
    880 /** \internal \returns the product of the elements of \a a */
    881 template <typename Packet>
    882 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_mul(
    883     const Packet& a) {
    884   typedef typename unpacket_traits<Packet>::type Scalar; 
    885   return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmul<Scalar>)));
    886 }
    887 
    888 /** \internal \returns the min of the elements of \a a */
    889 template <typename Packet>
    890 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(
    891     const Packet &a) {
    892   typedef typename unpacket_traits<Packet>::type Scalar; 
    893   return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<PropagateFast, Scalar>)));
    894 }
    895 
    896 template <int NaNPropagation, typename Packet>
    897 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_min(
    898     const Packet& a) {
    899   typedef typename unpacket_traits<Packet>::type Scalar; 
    900   return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmin<NaNPropagation, Scalar>)));
    901 }
    902 
    903 /** \internal \returns the min of the elements of \a a */
    904 template <typename Packet>
    905 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(
    906     const Packet &a) {
    907   typedef typename unpacket_traits<Packet>::type Scalar; 
    908   return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<PropagateFast, Scalar>)));
    909 }
    910 
    911 template <int NaNPropagation, typename Packet>
    912 EIGEN_DEVICE_FUNC inline typename unpacket_traits<Packet>::type predux_max(
    913     const Packet& a) {
    914   typedef typename unpacket_traits<Packet>::type Scalar; 
    915   return predux_helper(a, EIGEN_BINARY_OP_NAN_PROPAGATION(Scalar, (pmax<NaNPropagation, Scalar>)));
    916 }
    917 
    918 #undef EIGEN_BINARY_OP_NAN_PROPAGATION
    919 
    920 /** \internal \returns true if all coeffs of \a a means "true"
    921   * It is supposed to be called on values returned by pcmp_*.
    922   */
    923 // not needed yet
    924 // template<typename Packet> EIGEN_DEVICE_FUNC inline bool predux_all(const Packet& a)
    925 // { return bool(a); }
    926 
    927 /** \internal \returns true if any coeffs of \a a means "true"
    928   * It is supposed to be called on values returned by pcmp_*.
    929   */
    930 template<typename Packet> EIGEN_DEVICE_FUNC inline bool predux_any(const Packet& a)
    931 {
    932   // Dirty but generic implementation where "true" is assumed to be non 0 and all the sames.
    933   // It is expected that "true" is either:
    934   //  - Scalar(1)
    935   //  - bits full of ones (NaN for floats),
    936   //  - or first bit equals to 1 (1 for ints, smallest denormal for floats).
    937   // For all these cases, taking the sum is just fine, and this boils down to a no-op for scalars.
    938   typedef typename unpacket_traits<Packet>::type Scalar;
    939   return numext::not_equal_strict(predux(a), Scalar(0));
    940 }
    941 
    942 /***************************************************************************
    943 * The following functions might not have to be overwritten for vectorized types
    944 ***************************************************************************/
    945 
    946 /** \internal copy a packet with constant coefficient \a a (e.g., [a,a,a,a]) to \a *to. \a to must be 16 bytes aligned */
    947 // NOTE: this function must really be templated on the packet type (think about different packet types for the same scalar type)
    948 template<typename Packet>
    949 inline void pstore1(typename unpacket_traits<Packet>::type* to, const typename unpacket_traits<Packet>::type& a)
    950 {
    951   pstore(to, pset1<Packet>(a));
    952 }
    953 
    954 /** \internal \returns a * b + c (coeff-wise) */
    955 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
    956 pmadd(const Packet&  a,
    957          const Packet&  b,
    958          const Packet&  c)
    959 { return padd(pmul(a, b),c); }
    960 
    961 /** \internal \returns a packet version of \a *from.
    962   * The pointer \a from must be aligned on a \a Alignment bytes boundary. */
    963 template<typename Packet, int Alignment>
    964 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt(const typename unpacket_traits<Packet>::type* from)
    965 {
    966   if(Alignment >= unpacket_traits<Packet>::alignment)
    967     return pload<Packet>(from);
    968   else
    969     return ploadu<Packet>(from);
    970 }
    971 
    972 /** \internal copy the packet \a from to \a *to.
    973   * The pointer \a from must be aligned on a \a Alignment bytes boundary. */
    974 template<typename Scalar, typename Packet, int Alignment>
    975 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& from)
    976 {
    977   if(Alignment >= unpacket_traits<Packet>::alignment)
    978     pstore(to, from);
    979   else
    980     pstoreu(to, from);
    981 }
    982 
    983 /** \internal \returns a packet version of \a *from.
    984   * Unlike ploadt, ploadt_ro takes advantage of the read-only memory path on the
    985   * hardware if available to speedup the loading of data that won't be modified
    986   * by the current computation.
    987   */
    988 template<typename Packet, int LoadMode>
    989 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits<Packet>::type* from)
    990 {
    991   return ploadt<Packet, LoadMode>(from);
    992 }
    993 
    994 /***************************************************************************
    995 * Fast complex products (GCC generates a function call which is very slow)
    996 ***************************************************************************/
    997 
    998 // Eigen+CUDA does not support complexes.
    999 #if !defined(EIGEN_GPUCC)
   1000 
   1001 template<> inline std::complex<float> pmul(const std::complex<float>& a, const std::complex<float>& b)
   1002 { return std::complex<float>(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); }
   1003 
   1004 template<> inline std::complex<double> pmul(const std::complex<double>& a, const std::complex<double>& b)
   1005 { return std::complex<double>(a.real()*b.real() - a.imag()*b.imag(), a.imag()*b.real() + a.real()*b.imag()); }
   1006 
   1007 #endif
   1008 
   1009 
   1010 /***************************************************************************
   1011  * PacketBlock, that is a collection of N packets where the number of words
   1012  * in the packet is a multiple of N.
   1013 ***************************************************************************/
   1014 template <typename Packet,int N=unpacket_traits<Packet>::size> struct PacketBlock {
   1015   Packet packet[N];
   1016 };
   1017 
   1018 template<typename Packet> EIGEN_DEVICE_FUNC inline void
   1019 ptranspose(PacketBlock<Packet,1>& /*kernel*/) {
   1020   // Nothing to do in the scalar case, i.e. a 1x1 matrix.
   1021 }
   1022 
   1023 /***************************************************************************
   1024  * Selector, i.e. vector of N boolean values used to select (i.e. blend)
   1025  * words from 2 packets.
   1026 ***************************************************************************/
   1027 template <size_t N> struct Selector {
   1028   bool select[N];
   1029 };
   1030 
   1031 template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
   1032 pblend(const Selector<unpacket_traits<Packet>::size>& ifPacket, const Packet& thenPacket, const Packet& elsePacket) {
   1033   return ifPacket.select[0] ? thenPacket : elsePacket;
   1034 }
   1035 
   1036 } // end namespace internal
   1037 
   1038 } // end namespace Eigen
   1039 
   1040 #endif // EIGEN_GENERIC_PACKET_MATH_H