![]() |
Eigen
3.3.3
|
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