Eigen  3.3.3
PacketMath.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2016 Konstantinos Margaritis <markos@freevec.org>
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_PACKET_MATH_ZVECTOR_H
00011 #define EIGEN_PACKET_MATH_ZVECTOR_H
00012 
00013 #include <stdint.h>
00014 
00015 namespace Eigen {
00016 
00017 namespace internal {
00018 
00019 #ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD
00020 #define EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD 4
00021 #endif
00022 
00023 #ifndef EIGEN_HAS_SINGLE_INSTRUCTION_MADD
00024 #define EIGEN_HAS_SINGLE_INSTRUCTION_MADD
00025 #endif
00026 
00027 #ifndef EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
00028 #define EIGEN_HAS_SINGLE_INSTRUCTION_CJMADD
00029 #endif
00030 
00031 #ifndef EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS
00032 #define EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS  16
00033 #endif
00034 
00035 typedef __vector int                 Packet4i;
00036 typedef __vector unsigned int        Packet4ui;
00037 typedef __vector __bool int          Packet4bi;
00038 typedef __vector short int           Packet8i;
00039 typedef __vector unsigned char       Packet16uc;
00040 typedef __vector double              Packet2d;
00041 typedef __vector unsigned long long  Packet2ul;
00042 typedef __vector long long           Packet2l;
00043 
00044 typedef struct {
00045         Packet2d  v4f[2];
00046 } Packet4f;
00047 
00048 typedef union {
00049   int32_t   i[4];
00050   uint32_t ui[4];
00051   int64_t   l[2];
00052   uint64_t ul[2];
00053   double    d[2];
00054   Packet4i  v4i;
00055   Packet4ui v4ui;
00056   Packet2l  v2l;
00057   Packet2ul v2ul;
00058   Packet2d  v2d;
00059 } Packet;
00060 
00061 // We don't want to write the same code all the time, but we need to reuse the constants
00062 // and it doesn't really work to declare them global, so we define macros instead
00063 
00064 #define _EIGEN_DECLARE_CONST_FAST_Packet4i(NAME,X) \
00065   Packet4i p4i_##NAME = reinterpret_cast<Packet4i>(vec_splat_s32(X))
00066 
00067 #define _EIGEN_DECLARE_CONST_FAST_Packet2d(NAME,X) \
00068   Packet2d p2d_##NAME = reinterpret_cast<Packet2d>(vec_splat_s64(X))
00069 
00070 #define _EIGEN_DECLARE_CONST_FAST_Packet2l(NAME,X) \
00071   Packet2l p2l_##NAME = reinterpret_cast<Packet2l>(vec_splat_s64(X))
00072 
00073 #define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
00074   Packet4i p4i_##NAME = pset1<Packet4i>(X)
00075 
00076 #define _EIGEN_DECLARE_CONST_Packet2d(NAME,X) \
00077   Packet2d p2d_##NAME = pset1<Packet2d>(X)
00078 
00079 #define _EIGEN_DECLARE_CONST_Packet2l(NAME,X) \
00080   Packet2l p2l_##NAME = pset1<Packet2l>(X)
00081 
00082 // These constants are endian-agnostic
00083 //static _EIGEN_DECLARE_CONST_FAST_Packet4i(ZERO, 0); //{ 0, 0, 0, 0,}
00084 static _EIGEN_DECLARE_CONST_FAST_Packet4i(ONE, 1); //{ 1, 1, 1, 1}
00085 
00086 static _EIGEN_DECLARE_CONST_FAST_Packet2d(ZERO, 0);
00087 static _EIGEN_DECLARE_CONST_FAST_Packet2l(ZERO, 0);
00088 static _EIGEN_DECLARE_CONST_FAST_Packet2l(ONE, 1);
00089 
00090 static Packet2d p2d_ONE = { 1.0, 1.0 }; 
00091 static Packet2d p2d_ZERO_ = { -0.0, -0.0 };
00092 
00093 static Packet4i p4i_COUNTDOWN = { 0, 1, 2, 3 };
00094 static Packet4f p4f_COUNTDOWN = { 0.0, 1.0, 2.0, 3.0 };
00095 static Packet2d p2d_COUNTDOWN = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet16uc>(p2d_ZERO), reinterpret_cast<Packet16uc>(p2d_ONE), 8));
00096 
00097 static Packet16uc p16uc_PSET64_HI = { 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 };
00098 static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 };
00099 
00100 // Mask alignment
00101 #define _EIGEN_MASK_ALIGNMENT   0xfffffffffffffff0
00102 
00103 #define _EIGEN_ALIGNED_PTR(x)   ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
00104 
00105 // Handle endianness properly while loading constants
00106 // Define global static constants:
00107 
00108 static Packet16uc p16uc_FORWARD =   { 0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15 };
00109 static Packet16uc p16uc_REVERSE32 = { 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3 };
00110 static Packet16uc p16uc_REVERSE64 = { 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
00111 
00112 static Packet16uc p16uc_PSET32_WODD   = vec_sld((Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 0), (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 2), 8);//{ 0,1,2,3, 0,1,2,3, 8,9,10,11, 8,9,10,11 };
00113 static Packet16uc p16uc_PSET32_WEVEN  = vec_sld(p16uc_DUPLICATE32_HI, (Packet16uc) vec_splat((Packet4ui)p16uc_FORWARD, 3), 8);//{ 4,5,6,7, 4,5,6,7, 12,13,14,15, 12,13,14,15 };
00114 /*static Packet16uc p16uc_HALF64_0_16 = vec_sld((Packet16uc)p4i_ZERO, vec_splat((Packet16uc) vec_abs(p4i_MINUS16), 3), 8);      //{ 0,0,0,0, 0,0,0,0, 16,16,16,16, 16,16,16,16};
00115 
00116 static Packet16uc p16uc_PSET64_HI = (Packet16uc) vec_mergeh((Packet4ui)p16uc_PSET32_WODD, (Packet4ui)p16uc_PSET32_WEVEN);     //{ 0,1,2,3, 4,5,6,7, 0,1,2,3, 4,5,6,7 };*/
00117 static Packet16uc p16uc_PSET64_LO = (Packet16uc) vec_mergel((Packet4ui)p16uc_PSET32_WODD, (Packet4ui)p16uc_PSET32_WEVEN);     //{ 8,9,10,11, 12,13,14,15, 8,9,10,11, 12,13,14,15 };
00118 /*static Packet16uc p16uc_TRANSPOSE64_HI = vec_add(p16uc_PSET64_HI, p16uc_HALF64_0_16);                                         //{ 0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23};
00119 static Packet16uc p16uc_TRANSPOSE64_LO = vec_add(p16uc_PSET64_LO, p16uc_HALF64_0_16);                                         //{ 8,9,10,11, 12,13,14,15, 24,25,26,27, 28,29,30,31};*/
00120 static Packet16uc p16uc_TRANSPOSE64_HI = { 0,1,2,3, 4,5,6,7, 16,17,18,19, 20,21,22,23};
00121 static Packet16uc p16uc_TRANSPOSE64_LO = { 8,9,10,11, 12,13,14,15, 24,25,26,27, 28,29,30,31};
00122 
00123 //static Packet16uc p16uc_COMPLEX32_REV = vec_sld(p16uc_REVERSE32, p16uc_REVERSE32, 8);                                         //{ 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11 };
00124 
00125 //static Packet16uc p16uc_COMPLEX32_REV2 = vec_sld(p16uc_FORWARD, p16uc_FORWARD, 8);                                            //{ 8,9,10,11, 12,13,14,15, 0,1,2,3, 4,5,6,7 };
00126 
00127 
00128 #if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC
00129   #define EIGEN_ZVECTOR_PREFETCH(ADDR) __builtin_prefetch(ADDR);
00130 #else
00131   #define EIGEN_ZVECTOR_PREFETCH(ADDR) asm( "   pfd [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" );
00132 #endif
00133 
00134 template<> struct packet_traits<int>    : default_packet_traits
00135 {
00136   typedef Packet4i type;
00137   typedef Packet4i half;
00138   enum {
00139     Vectorizable = 1,
00140     AlignedOnScalar = 1,
00141     size = 4,
00142     HasHalfPacket = 0,
00143 
00144     HasAdd  = 1,
00145     HasSub  = 1,
00146     HasMul  = 1,
00147     HasDiv  = 1,
00148     HasBlend = 1
00149   };
00150 };
00151 
00152 template<> struct packet_traits<float> : default_packet_traits
00153 {
00154   typedef Packet4f type;
00155   typedef Packet4f half;
00156   enum {
00157     Vectorizable = 1,
00158     AlignedOnScalar = 1,
00159     size=4,
00160     HasHalfPacket = 0,
00161 
00162     HasAdd  = 1,
00163     HasSub  = 1,
00164     HasMul  = 1,
00165     HasDiv  = 1,
00166     HasMin  = 1,
00167     HasMax  = 1,
00168     HasAbs  = 1,
00169     HasSin  = 0,
00170     HasCos  = 0,
00171     HasLog  = 0,
00172     HasExp  = 1,
00173     HasSqrt = 1,
00174     HasRsqrt = 1,
00175     HasRound = 1,
00176     HasFloor = 1,
00177     HasCeil = 1,
00178     HasNegate = 1,
00179     HasBlend = 1
00180   };
00181 };
00182 
00183 template<> struct packet_traits<double> : default_packet_traits
00184 {
00185   typedef Packet2d type;
00186   typedef Packet2d half;
00187   enum {
00188     Vectorizable = 1,
00189     AlignedOnScalar = 1,
00190     size=2,
00191     HasHalfPacket = 1,
00192 
00193     HasAdd  = 1,
00194     HasSub  = 1,
00195     HasMul  = 1,
00196     HasDiv  = 1,
00197     HasMin  = 1,
00198     HasMax  = 1,
00199     HasAbs  = 1,
00200     HasSin  = 0,
00201     HasCos  = 0,
00202     HasLog  = 0,
00203     HasExp  = 1,
00204     HasSqrt = 1,
00205     HasRsqrt = 1,
00206     HasRound = 1,
00207     HasFloor = 1,
00208     HasCeil = 1,
00209     HasNegate = 1,
00210     HasBlend = 1
00211   };
00212 };
00213 
00214 template<> struct unpacket_traits<Packet4i> { typedef int    type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; };
00215 template<> struct unpacket_traits<Packet4f> { typedef float  type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; };
00216 template<> struct unpacket_traits<Packet2d> { typedef double type; enum {size=2, alignment=Aligned16}; typedef Packet2d half; };
00217 
00218 /* Forward declaration */
00219 EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet4f,4>& kernel);
00220  
00221 inline std::ostream & operator <<(std::ostream & s, const Packet4i & v)
00222 {
00223   Packet vt;
00224   vt.v4i = v;
00225   s << vt.i[0] << ", " << vt.i[1] << ", " << vt.i[2] << ", " << vt.i[3];
00226   return s;
00227 }
00228 
00229 inline std::ostream & operator <<(std::ostream & s, const Packet4ui & v)
00230 {
00231   Packet vt;
00232   vt.v4ui = v;
00233   s << vt.ui[0] << ", " << vt.ui[1] << ", " << vt.ui[2] << ", " << vt.ui[3];
00234   return s;
00235 }
00236 
00237 inline std::ostream & operator <<(std::ostream & s, const Packet2l & v)
00238 {
00239   Packet vt;
00240   vt.v2l = v;
00241   s << vt.l[0] << ", " << vt.l[1];
00242   return s;
00243 }
00244 
00245 inline std::ostream & operator <<(std::ostream & s, const Packet2ul & v)
00246 {
00247   Packet vt;
00248   vt.v2ul = v;
00249   s << vt.ul[0] << ", " << vt.ul[1] ;
00250   return s;
00251 }
00252 
00253 inline std::ostream & operator <<(std::ostream & s, const Packet2d & v)
00254 {
00255   Packet vt;
00256   vt.v2d = v;
00257   s << vt.d[0] << ", " << vt.d[1];
00258   return s;
00259 }
00260 
00261 /* Helper function to simulate a vec_splat_packet4f
00262  */
00263 template<int element> EIGEN_STRONG_INLINE Packet4f vec_splat_packet4f(const Packet4f&   from)
00264 {
00265   Packet4f splat;
00266   switch (element) {
00267   case 0:
00268     splat.v4f[0] = vec_splat(from.v4f[0], 0);
00269     splat.v4f[1] = splat.v4f[0];
00270     break;
00271   case 1:
00272     splat.v4f[0] = vec_splat(from.v4f[0], 1);
00273     splat.v4f[1] = splat.v4f[0];
00274     break;
00275   case 2:
00276     splat.v4f[0] = vec_splat(from.v4f[1], 0);
00277     splat.v4f[1] = splat.v4f[0];
00278     break;
00279   case 3:
00280     splat.v4f[0] = vec_splat(from.v4f[1], 1);
00281     splat.v4f[1] = splat.v4f[0];
00282     break;
00283   }
00284   return splat;
00285 }
00286 
00287 template<int Offset>
00288 struct palign_impl<Offset,Packet4i>
00289 {
00290   static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second)
00291   {
00292     switch (Offset % 4) {
00293     case 1:
00294       first = vec_sld(first, second, 4); break;
00295     case 2:
00296       first = vec_sld(first, second, 8); break;
00297     case 3:
00298       first = vec_sld(first, second, 12); break;
00299     }
00300   }
00301 };
00302 
00303 /* This is a tricky one, we have to translate float alignment to vector elements of sizeof double
00304  */
00305 template<int Offset>
00306 struct palign_impl<Offset,Packet4f>
00307 {
00308   static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second)
00309   {
00310     switch (Offset % 4) {
00311     case 1:
00312       first.v4f[0] = vec_sld(first.v4f[0], first.v4f[1], 8);
00313       first.v4f[1] = vec_sld(first.v4f[1], second.v4f[0], 8);
00314       break;
00315     case 2:
00316       first.v4f[0] = first.v4f[1];
00317       first.v4f[1] = second.v4f[0];
00318       break;
00319     case 3:
00320       first.v4f[0] = vec_sld(first.v4f[1],  second.v4f[0], 8);
00321       first.v4f[1] = vec_sld(second.v4f[0], second.v4f[1], 8);
00322       break;
00323     }
00324   }
00325 };
00326 
00327 
00328 template<int Offset>
00329 struct palign_impl<Offset,Packet2d>
00330 {
00331   static EIGEN_STRONG_INLINE void run(Packet2d& first, const Packet2d& second)
00332   {
00333     if (Offset == 1)
00334       first = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(first), reinterpret_cast<Packet4i>(second), 8));
00335   }
00336 };
00337 
00338 template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int*     from)
00339 {
00340   // FIXME: No intrinsic yet
00341   EIGEN_DEBUG_ALIGNED_LOAD
00342   Packet *vfrom;
00343   vfrom = (Packet *) from;
00344   return vfrom->v4i;
00345 }
00346 
00347 template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float*   from)
00348 {
00349   // FIXME: No intrinsic yet
00350   EIGEN_DEBUG_ALIGNED_LOAD
00351   Packet4f vfrom;
00352   vfrom.v4f[0] = vec_ld2f(&from[0]);
00353   vfrom.v4f[1] = vec_ld2f(&from[2]);
00354   return vfrom;
00355 }
00356 
00357 template<> EIGEN_STRONG_INLINE Packet2d pload<Packet2d>(const double* from)
00358 {
00359   // FIXME: No intrinsic yet
00360   EIGEN_DEBUG_ALIGNED_LOAD
00361   Packet *vfrom;
00362   vfrom = (Packet *) from;
00363   return vfrom->v2d;
00364 }
00365 
00366 template<> EIGEN_STRONG_INLINE void pstore<int>(int*       to, const Packet4i& from)
00367 {
00368   // FIXME: No intrinsic yet
00369   EIGEN_DEBUG_ALIGNED_STORE
00370   Packet *vto;
00371   vto = (Packet *) to;
00372   vto->v4i = from;
00373 }
00374 
00375 template<> EIGEN_STRONG_INLINE void pstore<float>(float*   to, const Packet4f& from)
00376 {
00377   // FIXME: No intrinsic yet
00378   EIGEN_DEBUG_ALIGNED_STORE
00379   vec_st2f(from.v4f[0], &to[0]);
00380   vec_st2f(from.v4f[1], &to[2]);
00381 }
00382 
00383 
00384 template<> EIGEN_STRONG_INLINE void pstore<double>(double*   to, const Packet2d& from)
00385 {
00386   // FIXME: No intrinsic yet
00387   EIGEN_DEBUG_ALIGNED_STORE
00388   Packet *vto;
00389   vto = (Packet *) to;
00390   vto->v2d = from;
00391 }
00392 
00393 template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int&    from)
00394 {
00395   return vec_splats(from);
00396 }
00397 template<> EIGEN_STRONG_INLINE Packet2d pset1<Packet2d>(const double& from) {
00398   return vec_splats(from);
00399 }
00400 template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float&    from)
00401 {
00402   Packet4f to;
00403   to.v4f[0] = pset1<Packet2d>(static_cast<const double&>(from));
00404   to.v4f[1] = to.v4f[0];
00405   return to;
00406 }
00407 
00408 template<> EIGEN_STRONG_INLINE void
00409 pbroadcast4<Packet4i>(const int *a,
00410                       Packet4i& a0, Packet4i& a1, Packet4i& a2, Packet4i& a3)
00411 {
00412   a3 = pload<Packet4i>(a);
00413   a0 = vec_splat(a3, 0);
00414   a1 = vec_splat(a3, 1);
00415   a2 = vec_splat(a3, 2);
00416   a3 = vec_splat(a3, 3);
00417 }
00418 
00419 template<> EIGEN_STRONG_INLINE void
00420 pbroadcast4<Packet4f>(const float *a,
00421                       Packet4f& a0, Packet4f& a1, Packet4f& a2, Packet4f& a3)
00422 {
00423   a3 = pload<Packet4f>(a);
00424   a0 = vec_splat_packet4f<0>(a3);
00425   a1 = vec_splat_packet4f<1>(a3);
00426   a2 = vec_splat_packet4f<2>(a3);
00427   a3 = vec_splat_packet4f<3>(a3);
00428 }
00429 
00430 template<> EIGEN_STRONG_INLINE void
00431 pbroadcast4<Packet2d>(const double *a,
00432                       Packet2d& a0, Packet2d& a1, Packet2d& a2, Packet2d& a3)
00433 {
00434   a1 = pload<Packet2d>(a);
00435   a0 = vec_splat(a1, 0);
00436   a1 = vec_splat(a1, 1);
00437   a3 = pload<Packet2d>(a+2);
00438   a2 = vec_splat(a3, 0);
00439   a3 = vec_splat(a3, 1);
00440 }
00441 
00442 template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, Index stride)
00443 {
00444   int EIGEN_ALIGN16 ai[4];
00445   ai[0] = from[0*stride];
00446   ai[1] = from[1*stride];
00447   ai[2] = from[2*stride];
00448   ai[3] = from[3*stride];
00449  return pload<Packet4i>(ai);
00450 }
00451 
00452 template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, Index stride)
00453 {
00454   float EIGEN_ALIGN16 ai[4];
00455   ai[0] = from[0*stride];
00456   ai[1] = from[1*stride];
00457   ai[2] = from[2*stride];
00458   ai[3] = from[3*stride];
00459  return pload<Packet4f>(ai);
00460 }
00461 
00462 template<> EIGEN_DEVICE_FUNC inline Packet2d pgather<double, Packet2d>(const double* from, Index stride)
00463 {
00464   double EIGEN_ALIGN16 af[2];
00465   af[0] = from[0*stride];
00466   af[1] = from[1*stride];
00467  return pload<Packet2d>(af);
00468 }
00469 
00470 template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, Index stride)
00471 {
00472   int EIGEN_ALIGN16 ai[4];
00473   pstore<int>((int *)ai, from);
00474   to[0*stride] = ai[0];
00475   to[1*stride] = ai[1];
00476   to[2*stride] = ai[2];
00477   to[3*stride] = ai[3];
00478 }
00479 
00480 template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, const Packet4f& from, Index stride)
00481 {
00482   float EIGEN_ALIGN16 ai[4];
00483   pstore<float>((float *)ai, from);
00484   to[0*stride] = ai[0];
00485   to[1*stride] = ai[1];
00486   to[2*stride] = ai[2];
00487   to[3*stride] = ai[3];
00488 }
00489 
00490 template<> EIGEN_DEVICE_FUNC inline void pscatter<double, Packet2d>(double* to, const Packet2d& from, Index stride)
00491 {
00492   double EIGEN_ALIGN16 af[2];
00493   pstore<double>(af, from);
00494   to[0*stride] = af[0];
00495   to[1*stride] = af[1];
00496 }
00497 
00498 template<> EIGEN_STRONG_INLINE Packet4i padd<Packet4i>(const Packet4i& a, const Packet4i& b) { return (a + b); }
00499 template<> EIGEN_STRONG_INLINE Packet4f padd<Packet4f>(const Packet4f& a, const Packet4f& b)
00500 {
00501   Packet4f c;
00502   c.v4f[0] = a.v4f[0] + b.v4f[0];
00503   c.v4f[1] = a.v4f[1] + b.v4f[1];
00504   return c;
00505 }
00506 template<> EIGEN_STRONG_INLINE Packet2d padd<Packet2d>(const Packet2d& a, const Packet2d& b) { return (a + b); }
00507 
00508 template<> EIGEN_STRONG_INLINE Packet4i psub<Packet4i>(const Packet4i& a, const Packet4i& b) { return (a - b); }
00509 template<> EIGEN_STRONG_INLINE Packet4f psub<Packet4f>(const Packet4f& a, const Packet4f& b)
00510 {
00511   Packet4f c;
00512   c.v4f[0] = a.v4f[0] - b.v4f[0];
00513   c.v4f[1] = a.v4f[1] - b.v4f[1];
00514   return c;
00515 }
00516 template<> EIGEN_STRONG_INLINE Packet2d psub<Packet2d>(const Packet2d& a, const Packet2d& b) { return (a - b); }
00517 
00518 template<> EIGEN_STRONG_INLINE Packet4i pmul<Packet4i>(const Packet4i& a, const Packet4i& b) { return (a * b); }
00519 template<> EIGEN_STRONG_INLINE Packet4f pmul<Packet4f>(const Packet4f& a, const Packet4f& b)
00520 {
00521   Packet4f c;
00522   c.v4f[0] = a.v4f[0] * b.v4f[0];
00523   c.v4f[1] = a.v4f[1] * b.v4f[1];
00524   return c;
00525 }
00526 template<> EIGEN_STRONG_INLINE Packet2d pmul<Packet2d>(const Packet2d& a, const Packet2d& b) { return (a * b); }
00527 
00528 template<> EIGEN_STRONG_INLINE Packet4i pdiv<Packet4i>(const Packet4i& a, const Packet4i& b) { return (a / b); }
00529 template<> EIGEN_STRONG_INLINE Packet4f pdiv<Packet4f>(const Packet4f& a, const Packet4f& b)
00530 {
00531   Packet4f c;
00532   c.v4f[0] = a.v4f[0] / b.v4f[0];
00533   c.v4f[1] = a.v4f[1] / b.v4f[1];
00534   return c;
00535 }
00536 template<> EIGEN_STRONG_INLINE Packet2d pdiv<Packet2d>(const Packet2d& a, const Packet2d& b) { return (a / b); }
00537 
00538 template<> EIGEN_STRONG_INLINE Packet4i pnegate(const Packet4i& a) { return (-a); }
00539 template<> EIGEN_STRONG_INLINE Packet4f pnegate(const Packet4f& a)
00540 {
00541   Packet4f c;
00542   c.v4f[0] = -a.v4f[0];
00543   c.v4f[1] = -a.v4f[1];
00544   return c;
00545 }
00546 template<> EIGEN_STRONG_INLINE Packet2d pnegate(const Packet2d& a) { return (-a); }
00547 
00548 template<> EIGEN_STRONG_INLINE Packet4i pconj(const Packet4i& a) { return a; }
00549 template<> EIGEN_STRONG_INLINE Packet4f pconj(const Packet4f& a) { return a; }
00550 template<> EIGEN_STRONG_INLINE Packet2d pconj(const Packet2d& a) { return a; }
00551 
00552 template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd<Packet4i>(pmul<Packet4i>(a, b), c); }
00553 template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c)
00554 {
00555   Packet4f res;
00556   res.v4f[0] = vec_madd(a.v4f[0], b.v4f[0], c.v4f[0]);
00557   res.v4f[1] = vec_madd(a.v4f[1], b.v4f[1], c.v4f[1]);
00558   return res;
00559 }
00560 template<> EIGEN_STRONG_INLINE Packet2d pmadd(const Packet2d& a, const Packet2d& b, const Packet2d& c) { return vec_madd(a, b, c); }
00561 
00562 template<> EIGEN_STRONG_INLINE Packet4i plset<Packet4i>(const int& a)    { return padd<Packet4i>(pset1<Packet4i>(a), p4i_COUNTDOWN); }
00563 template<> EIGEN_STRONG_INLINE Packet4f plset<Packet4f>(const float& a)  { return padd<Packet4f>(pset1<Packet4f>(a), p4f_COUNTDOWN); }
00564 template<> EIGEN_STRONG_INLINE Packet2d plset<Packet2d>(const double& a) { return padd<Packet2d>(pset1<Packet2d>(a), p2d_COUNTDOWN); }
00565 
00566 template<> EIGEN_STRONG_INLINE Packet4i pmin<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_min(a, b); }
00567 template<> EIGEN_STRONG_INLINE Packet2d pmin<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_min(a, b); }
00568 template<> EIGEN_STRONG_INLINE Packet4f pmin<Packet4f>(const Packet4f& a, const Packet4f& b)
00569 {
00570   Packet4f res;
00571   res.v4f[0] = pmin(a.v4f[0], b.v4f[0]);
00572   res.v4f[1] = pmin(a.v4f[1], b.v4f[1]);
00573   return res;
00574 }
00575 
00576 template<> EIGEN_STRONG_INLINE Packet4i pmax<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_max(a, b); }
00577 template<> EIGEN_STRONG_INLINE Packet2d pmax<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_max(a, b); }
00578 template<> EIGEN_STRONG_INLINE Packet4f pmax<Packet4f>(const Packet4f& a, const Packet4f& b)
00579 {
00580   Packet4f res;
00581   res.v4f[0] = pmax(a.v4f[0], b.v4f[0]);
00582   res.v4f[1] = pmax(a.v4f[1], b.v4f[1]);
00583   return res;
00584 }
00585 
00586 template<> EIGEN_STRONG_INLINE Packet4i pand<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_and(a, b); }
00587 template<> EIGEN_STRONG_INLINE Packet2d pand<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_and(a, b); }
00588 template<> EIGEN_STRONG_INLINE Packet4f pand<Packet4f>(const Packet4f& a, const Packet4f& b)
00589 {
00590   Packet4f res;
00591   res.v4f[0] = pand(a.v4f[0], b.v4f[0]);
00592   res.v4f[1] = pand(a.v4f[1], b.v4f[1]);
00593   return res;
00594 }
00595 
00596 template<> EIGEN_STRONG_INLINE Packet4i por<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_or(a, b); }
00597 template<> EIGEN_STRONG_INLINE Packet2d por<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_or(a, b); }
00598 template<> EIGEN_STRONG_INLINE Packet4f por<Packet4f>(const Packet4f& a, const Packet4f& b)
00599 {
00600   Packet4f res;
00601   res.v4f[0] = pand(a.v4f[0], b.v4f[0]);
00602   res.v4f[1] = pand(a.v4f[1], b.v4f[1]);
00603   return res;
00604 }
00605 
00606 template<> EIGEN_STRONG_INLINE Packet4i pxor<Packet4i>(const Packet4i& a, const Packet4i& b) { return vec_xor(a, b); }
00607 template<> EIGEN_STRONG_INLINE Packet2d pxor<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_xor(a, b); }
00608 template<> EIGEN_STRONG_INLINE Packet4f pxor<Packet4f>(const Packet4f& a, const Packet4f& b)
00609 {
00610   Packet4f res;
00611   res.v4f[0] = pand(a.v4f[0], b.v4f[0]);
00612   res.v4f[1] = pand(a.v4f[1], b.v4f[1]);
00613   return res;
00614 }
00615 
00616 template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return pand<Packet4i>(a, vec_nor(b, b)); }
00617 template<> EIGEN_STRONG_INLINE Packet2d pandnot<Packet2d>(const Packet2d& a, const Packet2d& b) { return vec_and(a, vec_nor(b, b)); }
00618 template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f& b)
00619 {
00620   Packet4f res;
00621   res.v4f[0] = pandnot(a.v4f[0], b.v4f[0]);
00622   res.v4f[1] = pandnot(a.v4f[1], b.v4f[1]);
00623   return res;
00624 }
00625 
00626 template<> EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a)
00627 {
00628   Packet4f res;
00629   res.v4f[0] = vec_round(a.v4f[0]);
00630   res.v4f[1] = vec_round(a.v4f[1]);
00631   return res;
00632 }
00633 template<> EIGEN_STRONG_INLINE Packet2d pround<Packet2d>(const Packet2d& a) { return vec_round(a); }
00634 template<> EIGEN_STRONG_INLINE Packet4f pceil<Packet4f>(const  Packet4f& a)
00635 {
00636   Packet4f res;
00637   res.v4f[0] = vec_ceil(a.v4f[0]);
00638   res.v4f[1] = vec_ceil(a.v4f[1]);
00639   return res;
00640 }
00641 template<> EIGEN_STRONG_INLINE Packet2d pceil<Packet2d>(const  Packet2d& a) { return vec_ceil(a); }
00642 template<> EIGEN_STRONG_INLINE Packet4f pfloor<Packet4f>(const Packet4f& a)
00643 {
00644   Packet4f res;
00645   res.v4f[0] = vec_floor(a.v4f[0]);
00646   res.v4f[1] = vec_floor(a.v4f[1]);
00647   return res;
00648 }
00649 template<> EIGEN_STRONG_INLINE Packet2d pfloor<Packet2d>(const Packet2d& a) { return vec_floor(a); }
00650 
00651 template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int*       from) { return pload<Packet4i>(from); }
00652 template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float*     from) { return pload<Packet4f>(from); }
00653 template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double*    from) { return pload<Packet2d>(from); }
00654 
00655 
00656 template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int*     from)
00657 {
00658   Packet4i p = pload<Packet4i>(from);
00659   return vec_perm(p, p, p16uc_DUPLICATE32_HI);
00660 }
00661 
00662 template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float*    from)
00663 {
00664   Packet4f p = pload<Packet4f>(from);
00665   p.v4f[1] = vec_splat(p.v4f[0], 1);
00666   p.v4f[0] = vec_splat(p.v4f[0], 0);
00667   return p;
00668 }
00669 
00670 template<> EIGEN_STRONG_INLINE Packet2d ploaddup<Packet2d>(const double*   from)
00671 {
00672   Packet2d p = pload<Packet2d>(from);
00673   return vec_perm(p, p, p16uc_PSET64_HI);
00674 }
00675 
00676 template<> EIGEN_STRONG_INLINE void pstoreu<int>(int*        to, const Packet4i& from) { pstore<int>(to, from); }
00677 template<> EIGEN_STRONG_INLINE void pstoreu<float>(float*    to, const Packet4f& from) { pstore<float>(to, from); }
00678 template<> EIGEN_STRONG_INLINE void pstoreu<double>(double*  to, const Packet2d& from) { pstore<double>(to, from); }
00679 
00680 template<> EIGEN_STRONG_INLINE void prefetch<int>(const int*       addr) { EIGEN_ZVECTOR_PREFETCH(addr); }
00681 template<> EIGEN_STRONG_INLINE void prefetch<float>(const float*   addr) { EIGEN_ZVECTOR_PREFETCH(addr); }
00682 template<> EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) { EIGEN_ZVECTOR_PREFETCH(addr); }
00683 
00684 template<> EIGEN_STRONG_INLINE int    pfirst<Packet4i>(const Packet4i& a) { int    EIGEN_ALIGN16 x[4]; pstore(x, a); return x[0]; }
00685 template<> EIGEN_STRONG_INLINE float  pfirst<Packet4f>(const Packet4f& a) { float  EIGEN_ALIGN16 x[2]; vec_st2f(a.v4f[0], &x[0]); return x[0]; }
00686 template<> EIGEN_STRONG_INLINE double pfirst<Packet2d>(const Packet2d& a) { double EIGEN_ALIGN16 x[2]; pstore(x, a); return x[0]; }
00687 
00688 template<> EIGEN_STRONG_INLINE Packet4i preverse(const Packet4i& a)
00689 {
00690   return reinterpret_cast<Packet4i>(vec_perm(reinterpret_cast<Packet16uc>(a), reinterpret_cast<Packet16uc>(a), p16uc_REVERSE32));
00691 }
00692 
00693 template<> EIGEN_STRONG_INLINE Packet2d preverse(const Packet2d& a)
00694 {
00695   return reinterpret_cast<Packet2d>(vec_perm(reinterpret_cast<Packet16uc>(a), reinterpret_cast<Packet16uc>(a), p16uc_REVERSE64));
00696 }
00697 
00698 template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a)
00699 {
00700   Packet4f rev;
00701   rev.v4f[0] = preverse<Packet2d>(a.v4f[1]);
00702   rev.v4f[1] = preverse<Packet2d>(a.v4f[0]);
00703   return rev;
00704 }
00705 
00706 template<> EIGEN_STRONG_INLINE Packet4i pabs<Packet4i>(const Packet4i& a) { return vec_abs(a); }
00707 template<> EIGEN_STRONG_INLINE Packet2d pabs<Packet2d>(const Packet2d& a) { return vec_abs(a); }
00708 template<> EIGEN_STRONG_INLINE Packet4f pabs<Packet4f>(const Packet4f& a)
00709 {
00710   Packet4f res;
00711   res.v4f[0] = pabs(a.v4f[0]);
00712   res.v4f[1] = pabs(a.v4f[1]);
00713   return res;
00714 }
00715 
00716 template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
00717 {
00718   Packet4i b, sum;
00719   b   = vec_sld(a, a, 8);
00720   sum = padd<Packet4i>(a, b);
00721   b   = vec_sld(sum, sum, 4);
00722   sum = padd<Packet4i>(sum, b);
00723   return pfirst(sum);
00724 }
00725 
00726 template<> EIGEN_STRONG_INLINE double predux<Packet2d>(const Packet2d& a)
00727 {
00728   Packet2d b, sum;
00729   b   = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(a), reinterpret_cast<Packet4i>(a), 8));
00730   sum = padd<Packet2d>(a, b);
00731   return pfirst(sum);
00732 }
00733 template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
00734 {
00735   Packet2d sum;
00736   sum = padd<Packet2d>(a.v4f[0], a.v4f[1]);
00737   double first = predux<Packet2d>(sum);
00738   return static_cast<float>(first);
00739 }
00740 
00741 template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
00742 {
00743   Packet4i v[4], sum[4];
00744 
00745   // It's easier and faster to transpose then add as columns
00746   // Check: http://www.freevec.org/function/matrix_4x4_transpose_floats for explanation
00747   // Do the transpose, first set of moves
00748   v[0] = vec_mergeh(vecs[0], vecs[2]);
00749   v[1] = vec_mergel(vecs[0], vecs[2]);
00750   v[2] = vec_mergeh(vecs[1], vecs[3]);
00751   v[3] = vec_mergel(vecs[1], vecs[3]);
00752   // Get the resulting vectors
00753   sum[0] = vec_mergeh(v[0], v[2]);
00754   sum[1] = vec_mergel(v[0], v[2]);
00755   sum[2] = vec_mergeh(v[1], v[3]);
00756   sum[3] = vec_mergel(v[1], v[3]);
00757 
00758   // Now do the summation:
00759   // Lines 0+1
00760   sum[0] = padd<Packet4i>(sum[0], sum[1]);
00761   // Lines 2+3
00762   sum[1] = padd<Packet4i>(sum[2], sum[3]);
00763   // Add the results
00764   sum[0] = padd<Packet4i>(sum[0], sum[1]);
00765 
00766   return sum[0];
00767 }
00768 
00769 template<> EIGEN_STRONG_INLINE Packet2d preduxp<Packet2d>(const Packet2d* vecs)
00770 {
00771   Packet2d v[2], sum;
00772   v[0] = padd<Packet2d>(vecs[0], reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(vecs[0]), reinterpret_cast<Packet4ui>(vecs[0]), 8)));
00773   v[1] = padd<Packet2d>(vecs[1], reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(vecs[1]), reinterpret_cast<Packet4ui>(vecs[1]), 8)));
00774  
00775   sum = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v[0]), reinterpret_cast<Packet4ui>(v[1]), 8));
00776 
00777   return sum;
00778 }
00779 
00780 template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
00781 {
00782   PacketBlock<Packet4f,4> transpose;
00783   transpose.packet[0] = vecs[0];
00784   transpose.packet[1] = vecs[1];
00785   transpose.packet[2] = vecs[2];
00786   transpose.packet[3] = vecs[3];
00787   ptranspose(transpose);
00788 
00789   Packet4f sum = padd(transpose.packet[0], transpose.packet[1]);
00790   sum = padd(sum, transpose.packet[2]);
00791   sum = padd(sum, transpose.packet[3]);
00792   return sum;
00793 }
00794 
00795 // Other reduction functions:
00796 // mul
00797 template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
00798 {
00799   EIGEN_ALIGN16 int aux[4];
00800   pstore(aux, a);
00801   return aux[0] * aux[1] * aux[2] * aux[3];
00802 }
00803 
00804 template<> EIGEN_STRONG_INLINE double predux_mul<Packet2d>(const Packet2d& a)
00805 {
00806   return pfirst(pmul(a, reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(a), reinterpret_cast<Packet4i>(a), 8))));
00807 }
00808 
00809 template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
00810 {
00811   // Return predux_mul<Packet2d> of the subvectors product
00812   return static_cast<float>(pfirst(predux_mul(pmul(a.v4f[0], a.v4f[1]))));
00813 }
00814 
00815 // min
00816 template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
00817 {
00818   Packet4i b, res;
00819   b   = pmin<Packet4i>(a, vec_sld(a, a, 8));
00820   res = pmin<Packet4i>(b, vec_sld(b, b, 4));
00821   return pfirst(res);
00822 }
00823 
00824 template<> EIGEN_STRONG_INLINE double predux_min<Packet2d>(const Packet2d& a)
00825 {
00826   return pfirst(pmin<Packet2d>(a, reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(a), reinterpret_cast<Packet4i>(a), 8))));
00827 }
00828 
00829 template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
00830 {
00831   Packet2d b, res;
00832   b   = pmin<Packet2d>(a.v4f[0], a.v4f[1]);
00833   res = pmin<Packet2d>(b, reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(b), reinterpret_cast<Packet4i>(b), 8)));
00834   return static_cast<float>(pfirst(res));
00835 }
00836 
00837 // max
00838 template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
00839 {
00840   Packet4i b, res;
00841   b = pmax<Packet4i>(a, vec_sld(a, a, 8));
00842   res = pmax<Packet4i>(b, vec_sld(b, b, 4));
00843   return pfirst(res);
00844 }
00845 
00846 // max
00847 template<> EIGEN_STRONG_INLINE double predux_max<Packet2d>(const Packet2d& a)
00848 {
00849   return pfirst(pmax<Packet2d>(a, reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(a), reinterpret_cast<Packet4i>(a), 8))));
00850 }
00851 
00852 template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
00853 {
00854   Packet2d b, res;
00855   b   = pmax<Packet2d>(a.v4f[0], a.v4f[1]);
00856   res = pmax<Packet2d>(b, reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4i>(b), reinterpret_cast<Packet4i>(b), 8)));
00857   return static_cast<float>(pfirst(res));
00858 }
00859 
00860 EIGEN_DEVICE_FUNC inline void
00861 ptranspose(PacketBlock<Packet4i,4>& kernel) {
00862   Packet4i t0 = vec_mergeh(kernel.packet[0], kernel.packet[2]);
00863   Packet4i t1 = vec_mergel(kernel.packet[0], kernel.packet[2]);
00864   Packet4i t2 = vec_mergeh(kernel.packet[1], kernel.packet[3]);
00865   Packet4i t3 = vec_mergel(kernel.packet[1], kernel.packet[3]);
00866   kernel.packet[0] = vec_mergeh(t0, t2);
00867   kernel.packet[1] = vec_mergel(t0, t2);
00868   kernel.packet[2] = vec_mergeh(t1, t3);
00869   kernel.packet[3] = vec_mergel(t1, t3);
00870 }
00871 
00872 EIGEN_DEVICE_FUNC inline void
00873 ptranspose(PacketBlock<Packet2d,2>& kernel) {
00874   Packet2d t0 = vec_perm(kernel.packet[0], kernel.packet[1], p16uc_TRANSPOSE64_HI);
00875   Packet2d t1 = vec_perm(kernel.packet[0], kernel.packet[1], p16uc_TRANSPOSE64_LO);
00876   kernel.packet[0] = t0;
00877   kernel.packet[1] = t1;
00878 }
00879 
00880 /* Split the Packet4f PacketBlock into 4 Packet2d PacketBlocks and transpose each one
00881  */
00882 EIGEN_DEVICE_FUNC inline void
00883 ptranspose(PacketBlock<Packet4f,4>& kernel) {
00884   PacketBlock<Packet2d,2> t0,t1,t2,t3;
00885   // copy top-left 2x2 Packet2d block
00886   t0.packet[0] = kernel.packet[0].v4f[0];
00887   t0.packet[1] = kernel.packet[1].v4f[0];
00888 
00889   // copy top-right 2x2 Packet2d block
00890   t1.packet[0] = kernel.packet[0].v4f[1];
00891   t1.packet[1] = kernel.packet[1].v4f[1];
00892 
00893   // copy bottom-left 2x2 Packet2d block
00894   t2.packet[0] = kernel.packet[2].v4f[0];
00895   t2.packet[1] = kernel.packet[3].v4f[0];
00896 
00897   // copy bottom-right 2x2 Packet2d block
00898   t3.packet[0] = kernel.packet[2].v4f[1];
00899   t3.packet[1] = kernel.packet[3].v4f[1];
00900 
00901   // Transpose all 2x2 blocks
00902   ptranspose(t0);
00903   ptranspose(t1);
00904   ptranspose(t2);
00905   ptranspose(t3);
00906 
00907   // Copy back transposed blocks, but exchange t1 and t2 due to transposition
00908   kernel.packet[0].v4f[0] = t0.packet[0];
00909   kernel.packet[0].v4f[1] = t2.packet[0];
00910   kernel.packet[1].v4f[0] = t0.packet[1];
00911   kernel.packet[1].v4f[1] = t2.packet[1];
00912   kernel.packet[2].v4f[0] = t1.packet[0];
00913   kernel.packet[2].v4f[1] = t3.packet[0];
00914   kernel.packet[3].v4f[0] = t1.packet[1];
00915   kernel.packet[3].v4f[1] = t3.packet[1];
00916 }
00917 
00918 template<> EIGEN_STRONG_INLINE Packet4i pblend(const Selector<4>& ifPacket, const Packet4i& thenPacket, const Packet4i& elsePacket) {
00919   Packet4ui select = { ifPacket.select[0], ifPacket.select[1], ifPacket.select[2], ifPacket.select[3] };
00920   Packet4ui mask = vec_cmpeq(select, reinterpret_cast<Packet4ui>(p4i_ONE));
00921   return vec_sel(elsePacket, thenPacket, mask);
00922 }
00923 
00924 template<> EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& thenPacket, const Packet4f& elsePacket) {
00925   Packet2ul select_hi = { ifPacket.select[0], ifPacket.select[1] };
00926   Packet2ul select_lo = { ifPacket.select[2], ifPacket.select[3] };
00927   Packet2ul mask_hi = vec_cmpeq(select_hi, reinterpret_cast<Packet2ul>(p2l_ONE));
00928   Packet2ul mask_lo = vec_cmpeq(select_lo, reinterpret_cast<Packet2ul>(p2l_ONE));
00929   Packet4f result;
00930   result.v4f[0] = vec_sel(elsePacket.v4f[0], thenPacket.v4f[0], mask_hi);
00931   result.v4f[1] = vec_sel(elsePacket.v4f[1], thenPacket.v4f[1], mask_lo);
00932   return result;
00933 }
00934 
00935 template<> EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d& thenPacket, const Packet2d& elsePacket) {
00936   Packet2ul select = { ifPacket.select[0], ifPacket.select[1] };
00937   Packet2ul mask = vec_cmpeq(select, reinterpret_cast<Packet2ul>(p2l_ONE));
00938   return vec_sel(elsePacket, thenPacket, mask);
00939 }
00940 
00941 } // end namespace internal
00942 
00943 } // end namespace Eigen
00944 
00945 #endif // EIGEN_PACKET_MATH_ZVECTOR_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends