File indexing completed on 2025-01-19 09:51:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_PACKET_MATH_GPU_H
0011 #define EIGEN_PACKET_MATH_GPU_H
0012
0013 namespace Eigen {
0014
0015 namespace internal {
0016
0017
0018 #if defined(EIGEN_HIP_DEVICE_COMPILE) || (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 350)
0019 #define EIGEN_GPU_HAS_LDG 1
0020 #endif
0021
0022
0023 #if (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530)
0024 #define EIGEN_CUDA_HAS_FP16_ARITHMETIC 1
0025 #endif
0026
0027 #if defined(EIGEN_HIP_DEVICE_COMPILE) || defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
0028 #define EIGEN_GPU_HAS_FP16_ARITHMETIC 1
0029 #endif
0030
0031
0032
0033
0034 #if defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
0035
0036 template<> struct is_arithmetic<float4> { enum { value = true }; };
0037 template<> struct is_arithmetic<double2> { enum { value = true }; };
0038
0039 template<> struct packet_traits<float> : default_packet_traits
0040 {
0041 typedef float4 type;
0042 typedef float4 half;
0043 enum {
0044 Vectorizable = 1,
0045 AlignedOnScalar = 1,
0046 size=4,
0047 HasHalfPacket = 0,
0048
0049 HasDiv = 1,
0050 HasSin = 0,
0051 HasCos = 0,
0052 HasLog = 1,
0053 HasExp = 1,
0054 HasSqrt = 1,
0055 HasRsqrt = 1,
0056 HasLGamma = 1,
0057 HasDiGamma = 1,
0058 HasZeta = 1,
0059 HasPolygamma = 1,
0060 HasErf = 1,
0061 HasErfc = 1,
0062 HasNdtri = 1,
0063 HasBessel = 1,
0064 HasIGamma = 1,
0065 HasIGammaDerA = 1,
0066 HasGammaSampleDerAlpha = 1,
0067 HasIGammac = 1,
0068 HasBetaInc = 1,
0069
0070 HasBlend = 0,
0071 HasFloor = 1,
0072 };
0073 };
0074
0075 template<> struct packet_traits<double> : default_packet_traits
0076 {
0077 typedef double2 type;
0078 typedef double2 half;
0079 enum {
0080 Vectorizable = 1,
0081 AlignedOnScalar = 1,
0082 size=2,
0083 HasHalfPacket = 0,
0084
0085 HasDiv = 1,
0086 HasLog = 1,
0087 HasExp = 1,
0088 HasSqrt = 1,
0089 HasRsqrt = 1,
0090 HasLGamma = 1,
0091 HasDiGamma = 1,
0092 HasZeta = 1,
0093 HasPolygamma = 1,
0094 HasErf = 1,
0095 HasErfc = 1,
0096 HasNdtri = 1,
0097 HasBessel = 1,
0098 HasIGamma = 1,
0099 HasIGammaDerA = 1,
0100 HasGammaSampleDerAlpha = 1,
0101 HasIGammac = 1,
0102 HasBetaInc = 1,
0103
0104 HasBlend = 0,
0105 HasFloor = 1,
0106 };
0107 };
0108
0109
0110 template<> struct unpacket_traits<float4> { typedef float type; enum {size=4, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef float4 half; };
0111 template<> struct unpacket_traits<double2> { typedef double type; enum {size=2, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef double2 half; };
0112
0113 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pset1<float4>(const float& from) {
0114 return make_float4(from, from, from, from);
0115 }
0116 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pset1<double2>(const double& from) {
0117 return make_double2(from, from);
0118 }
0119
0120
0121
0122
0123 #if defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
0124 namespace {
0125
0126 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_and(const float& a,
0127 const float& b) {
0128 return __int_as_float(__float_as_int(a) & __float_as_int(b));
0129 }
0130 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_and(const double& a,
0131 const double& b) {
0132 return __longlong_as_double(__double_as_longlong(a) &
0133 __double_as_longlong(b));
0134 }
0135
0136 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_or(const float& a,
0137 const float& b) {
0138 return __int_as_float(__float_as_int(a) | __float_as_int(b));
0139 }
0140 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_or(const double& a,
0141 const double& b) {
0142 return __longlong_as_double(__double_as_longlong(a) |
0143 __double_as_longlong(b));
0144 }
0145
0146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_xor(const float& a,
0147 const float& b) {
0148 return __int_as_float(__float_as_int(a) ^ __float_as_int(b));
0149 }
0150 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_xor(const double& a,
0151 const double& b) {
0152 return __longlong_as_double(__double_as_longlong(a) ^
0153 __double_as_longlong(b));
0154 }
0155
0156 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_andnot(const float& a,
0157 const float& b) {
0158 return __int_as_float(__float_as_int(a) & ~__float_as_int(b));
0159 }
0160 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_andnot(const double& a,
0161 const double& b) {
0162 return __longlong_as_double(__double_as_longlong(a) &
0163 ~__double_as_longlong(b));
0164 }
0165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float eq_mask(const float& a,
0166 const float& b) {
0167 return __int_as_float(a == b ? 0xffffffffu : 0u);
0168 }
0169 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double eq_mask(const double& a,
0170 const double& b) {
0171 return __longlong_as_double(a == b ? 0xffffffffffffffffull : 0ull);
0172 }
0173
0174 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float lt_mask(const float& a,
0175 const float& b) {
0176 return __int_as_float(a < b ? 0xffffffffu : 0u);
0177 }
0178 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double lt_mask(const double& a,
0179 const double& b) {
0180 return __longlong_as_double(a < b ? 0xffffffffffffffffull : 0ull);
0181 }
0182
0183 }
0184
0185 template <>
0186 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pand<float4>(const float4& a,
0187 const float4& b) {
0188 return make_float4(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y),
0189 bitwise_and(a.z, b.z), bitwise_and(a.w, b.w));
0190 }
0191 template <>
0192 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pand<double2>(const double2& a,
0193 const double2& b) {
0194 return make_double2(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y));
0195 }
0196
0197 template <>
0198 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 por<float4>(const float4& a,
0199 const float4& b) {
0200 return make_float4(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y),
0201 bitwise_or(a.z, b.z), bitwise_or(a.w, b.w));
0202 }
0203 template <>
0204 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 por<double2>(const double2& a,
0205 const double2& b) {
0206 return make_double2(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y));
0207 }
0208
0209 template <>
0210 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pxor<float4>(const float4& a,
0211 const float4& b) {
0212 return make_float4(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y),
0213 bitwise_xor(a.z, b.z), bitwise_xor(a.w, b.w));
0214 }
0215 template <>
0216 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pxor<double2>(const double2& a,
0217 const double2& b) {
0218 return make_double2(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y));
0219 }
0220
0221 template <>
0222 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pandnot<float4>(const float4& a,
0223 const float4& b) {
0224 return make_float4(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y),
0225 bitwise_andnot(a.z, b.z), bitwise_andnot(a.w, b.w));
0226 }
0227 template <>
0228 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
0229 pandnot<double2>(const double2& a, const double2& b) {
0230 return make_double2(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y));
0231 }
0232
0233 template <>
0234 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_eq<float4>(const float4& a,
0235 const float4& b) {
0236 return make_float4(eq_mask(a.x, b.x), eq_mask(a.y, b.y), eq_mask(a.z, b.z),
0237 eq_mask(a.w, b.w));
0238 }
0239 template <>
0240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_lt<float4>(const float4& a,
0241 const float4& b) {
0242 return make_float4(lt_mask(a.x, b.x), lt_mask(a.y, b.y), lt_mask(a.z, b.z),
0243 lt_mask(a.w, b.w));
0244 }
0245 template <>
0246 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
0247 pcmp_eq<double2>(const double2& a, const double2& b) {
0248 return make_double2(eq_mask(a.x, b.x), eq_mask(a.y, b.y));
0249 }
0250 template <>
0251 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
0252 pcmp_lt<double2>(const double2& a, const double2& b) {
0253 return make_double2(lt_mask(a.x, b.x), lt_mask(a.y, b.y));
0254 }
0255 #endif
0256
0257 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 plset<float4>(const float& a) {
0258 return make_float4(a, a+1, a+2, a+3);
0259 }
0260 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 plset<double2>(const double& a) {
0261 return make_double2(a, a+1);
0262 }
0263
0264 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 padd<float4>(const float4& a, const float4& b) {
0265 return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
0266 }
0267 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 padd<double2>(const double2& a, const double2& b) {
0268 return make_double2(a.x+b.x, a.y+b.y);
0269 }
0270
0271 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 psub<float4>(const float4& a, const float4& b) {
0272 return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
0273 }
0274 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 psub<double2>(const double2& a, const double2& b) {
0275 return make_double2(a.x-b.x, a.y-b.y);
0276 }
0277
0278 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pnegate(const float4& a) {
0279 return make_float4(-a.x, -a.y, -a.z, -a.w);
0280 }
0281 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pnegate(const double2& a) {
0282 return make_double2(-a.x, -a.y);
0283 }
0284
0285 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pconj(const float4& a) { return a; }
0286 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pconj(const double2& a) { return a; }
0287
0288 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmul<float4>(const float4& a, const float4& b) {
0289 return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
0290 }
0291 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmul<double2>(const double2& a, const double2& b) {
0292 return make_double2(a.x*b.x, a.y*b.y);
0293 }
0294
0295 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pdiv<float4>(const float4& a, const float4& b) {
0296 return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
0297 }
0298 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pdiv<double2>(const double2& a, const double2& b) {
0299 return make_double2(a.x/b.x, a.y/b.y);
0300 }
0301
0302 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmin<float4>(const float4& a, const float4& b) {
0303 return make_float4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w));
0304 }
0305 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmin<double2>(const double2& a, const double2& b) {
0306 return make_double2(fmin(a.x, b.x), fmin(a.y, b.y));
0307 }
0308
0309 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmax<float4>(const float4& a, const float4& b) {
0310 return make_float4(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z), fmaxf(a.w, b.w));
0311 }
0312 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmax<double2>(const double2& a, const double2& b) {
0313 return make_double2(fmax(a.x, b.x), fmax(a.y, b.y));
0314 }
0315
0316 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pload<float4>(const float* from) {
0317 return *reinterpret_cast<const float4*>(from);
0318 }
0319
0320 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pload<double2>(const double* from) {
0321 return *reinterpret_cast<const double2*>(from);
0322 }
0323
0324 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploadu<float4>(const float* from) {
0325 return make_float4(from[0], from[1], from[2], from[3]);
0326 }
0327 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploadu<double2>(const double* from) {
0328 return make_double2(from[0], from[1]);
0329 }
0330
0331 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploaddup<float4>(const float* from) {
0332 return make_float4(from[0], from[0], from[1], from[1]);
0333 }
0334 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploaddup<double2>(const double* from) {
0335 return make_double2(from[0], from[0]);
0336 }
0337
0338 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<float>(float* to, const float4& from) {
0339 *reinterpret_cast<float4*>(to) = from;
0340 }
0341
0342 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<double>(double* to, const double2& from) {
0343 *reinterpret_cast<double2*>(to) = from;
0344 }
0345
0346 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const float4& from) {
0347 to[0] = from.x;
0348 to[1] = from.y;
0349 to[2] = from.z;
0350 to[3] = from.w;
0351 }
0352
0353 template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const double2& from) {
0354 to[0] = from.x;
0355 to[1] = from.y;
0356 }
0357
0358 template<>
0359 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Aligned>(const float* from) {
0360 #if defined(EIGEN_GPU_HAS_LDG)
0361 return __ldg((const float4*)from);
0362 #else
0363 return make_float4(from[0], from[1], from[2], from[3]);
0364 #endif
0365 }
0366 template<>
0367 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Aligned>(const double* from) {
0368 #if defined(EIGEN_GPU_HAS_LDG)
0369 return __ldg((const double2*)from);
0370 #else
0371 return make_double2(from[0], from[1]);
0372 #endif
0373 }
0374
0375 template<>
0376 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Unaligned>(const float* from) {
0377 #if defined(EIGEN_GPU_HAS_LDG)
0378 return make_float4(__ldg(from+0), __ldg(from+1), __ldg(from+2), __ldg(from+3));
0379 #else
0380 return make_float4(from[0], from[1], from[2], from[3]);
0381 #endif
0382 }
0383 template<>
0384 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Unaligned>(const double* from) {
0385 #if defined(EIGEN_GPU_HAS_LDG)
0386 return make_double2(__ldg(from+0), __ldg(from+1));
0387 #else
0388 return make_double2(from[0], from[1]);
0389 #endif
0390 }
0391
0392 template<> EIGEN_DEVICE_FUNC inline float4 pgather<float, float4>(const float* from, Index stride) {
0393 return make_float4(from[0*stride], from[1*stride], from[2*stride], from[3*stride]);
0394 }
0395
0396 template<> EIGEN_DEVICE_FUNC inline double2 pgather<double, double2>(const double* from, Index stride) {
0397 return make_double2(from[0*stride], from[1*stride]);
0398 }
0399
0400 template<> EIGEN_DEVICE_FUNC inline void pscatter<float, float4>(float* to, const float4& from, Index stride) {
0401 to[stride*0] = from.x;
0402 to[stride*1] = from.y;
0403 to[stride*2] = from.z;
0404 to[stride*3] = from.w;
0405 }
0406 template<> EIGEN_DEVICE_FUNC inline void pscatter<double, double2>(double* to, const double2& from, Index stride) {
0407 to[stride*0] = from.x;
0408 to[stride*1] = from.y;
0409 }
0410
0411 template<> EIGEN_DEVICE_FUNC inline float pfirst<float4>(const float4& a) {
0412 return a.x;
0413 }
0414 template<> EIGEN_DEVICE_FUNC inline double pfirst<double2>(const double2& a) {
0415 return a.x;
0416 }
0417
0418 template<> EIGEN_DEVICE_FUNC inline float predux<float4>(const float4& a) {
0419 return a.x + a.y + a.z + a.w;
0420 }
0421 template<> EIGEN_DEVICE_FUNC inline double predux<double2>(const double2& a) {
0422 return a.x + a.y;
0423 }
0424
0425 template<> EIGEN_DEVICE_FUNC inline float predux_max<float4>(const float4& a) {
0426 return fmaxf(fmaxf(a.x, a.y), fmaxf(a.z, a.w));
0427 }
0428 template<> EIGEN_DEVICE_FUNC inline double predux_max<double2>(const double2& a) {
0429 return fmax(a.x, a.y);
0430 }
0431
0432 template<> EIGEN_DEVICE_FUNC inline float predux_min<float4>(const float4& a) {
0433 return fminf(fminf(a.x, a.y), fminf(a.z, a.w));
0434 }
0435 template<> EIGEN_DEVICE_FUNC inline double predux_min<double2>(const double2& a) {
0436 return fmin(a.x, a.y);
0437 }
0438
0439 template<> EIGEN_DEVICE_FUNC inline float predux_mul<float4>(const float4& a) {
0440 return a.x * a.y * a.z * a.w;
0441 }
0442 template<> EIGEN_DEVICE_FUNC inline double predux_mul<double2>(const double2& a) {
0443 return a.x * a.y;
0444 }
0445
0446 template<> EIGEN_DEVICE_FUNC inline float4 pabs<float4>(const float4& a) {
0447 return make_float4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w));
0448 }
0449 template<> EIGEN_DEVICE_FUNC inline double2 pabs<double2>(const double2& a) {
0450 return make_double2(fabs(a.x), fabs(a.y));
0451 }
0452
0453 template<> EIGEN_DEVICE_FUNC inline float4 pfloor<float4>(const float4& a) {
0454 return make_float4(floorf(a.x), floorf(a.y), floorf(a.z), floorf(a.w));
0455 }
0456 template<> EIGEN_DEVICE_FUNC inline double2 pfloor<double2>(const double2& a) {
0457 return make_double2(floor(a.x), floor(a.y));
0458 }
0459
0460 EIGEN_DEVICE_FUNC inline void
0461 ptranspose(PacketBlock<float4,4>& kernel) {
0462 float tmp = kernel.packet[0].y;
0463 kernel.packet[0].y = kernel.packet[1].x;
0464 kernel.packet[1].x = tmp;
0465
0466 tmp = kernel.packet[0].z;
0467 kernel.packet[0].z = kernel.packet[2].x;
0468 kernel.packet[2].x = tmp;
0469
0470 tmp = kernel.packet[0].w;
0471 kernel.packet[0].w = kernel.packet[3].x;
0472 kernel.packet[3].x = tmp;
0473
0474 tmp = kernel.packet[1].z;
0475 kernel.packet[1].z = kernel.packet[2].y;
0476 kernel.packet[2].y = tmp;
0477
0478 tmp = kernel.packet[1].w;
0479 kernel.packet[1].w = kernel.packet[3].y;
0480 kernel.packet[3].y = tmp;
0481
0482 tmp = kernel.packet[2].w;
0483 kernel.packet[2].w = kernel.packet[3].z;
0484 kernel.packet[3].z = tmp;
0485 }
0486
0487 EIGEN_DEVICE_FUNC inline void
0488 ptranspose(PacketBlock<double2,2>& kernel) {
0489 double tmp = kernel.packet[0].y;
0490 kernel.packet[0].y = kernel.packet[1].x;
0491 kernel.packet[1].x = tmp;
0492 }
0493
0494 #endif
0495
0496
0497
0498 #if defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)
0499
0500 typedef ulonglong2 Packet4h2;
0501 template<> struct unpacket_traits<Packet4h2> { typedef Eigen::half type; enum {size=8, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef Packet4h2 half; };
0502 template<> struct is_arithmetic<Packet4h2> { enum { value = true }; };
0503
0504 template<> struct unpacket_traits<half2> { typedef Eigen::half type; enum {size=2, alignment=Aligned16, vectorizable=true, masked_load_available=false, masked_store_available=false}; typedef half2 half; };
0505 template<> struct is_arithmetic<half2> { enum { value = true }; };
0506
0507 template<> struct packet_traits<Eigen::half> : default_packet_traits
0508 {
0509 typedef Packet4h2 type;
0510 typedef Packet4h2 half;
0511 enum {
0512 Vectorizable = 1,
0513 AlignedOnScalar = 1,
0514 size=8,
0515 HasHalfPacket = 0,
0516 HasAdd = 1,
0517 HasSub = 1,
0518 HasMul = 1,
0519 HasDiv = 1,
0520 HasSqrt = 1,
0521 HasRsqrt = 1,
0522 HasExp = 1,
0523 HasExpm1 = 1,
0524 HasLog = 1,
0525 HasLog1p = 1
0526 };
0527 };
0528
0529 namespace {
0530
0531 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 combine_half(const __half& a, const __half& b) {
0532 #if defined(EIGEN_GPU_COMPILE_PHASE)
0533 return __halves2half2(a, b);
0534 #else
0535
0536 return __floats2half2_rn(__half2float(a), __half2float(b));
0537 #endif
0538 }
0539
0540 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE __half get_half2_low(const half2& a) {
0541 #if defined(EIGEN_GPU_COMPILE_PHASE)
0542 return __low2half(a);
0543 #else
0544 return __float2half(__low2float(a));
0545 #endif
0546 }
0547
0548 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE __half get_half2_high(const half2& a) {
0549 #if defined(EIGEN_GPU_COMPILE_PHASE)
0550 return __high2half(a);
0551 #else
0552 return __float2half(__high2float(a));
0553 #endif
0554 }
0555 }
0556
0557 template<>
0558 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
0559 #if defined(EIGEN_GPU_COMPILE_PHASE)
0560 return __half2half2(from);
0561 #else
0562 const float f = __half2float(from);
0563 return __floats2half2_rn(f, f);
0564 #endif
0565 }
0566
0567 template <>
0568 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
0569 pset1<Packet4h2>(const Eigen::half& from) {
0570 Packet4h2 r;
0571 half2* p_alias = reinterpret_cast<half2*>(&r);
0572 p_alias[0] = pset1<half2>(from);
0573 p_alias[1] = pset1<half2>(from);
0574 p_alias[2] = pset1<half2>(from);
0575 p_alias[3] = pset1<half2>(from);
0576 return r;
0577 }
0578
0579
0580
0581 namespace {
0582
0583 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const Eigen::half* from) {
0584 return *reinterpret_cast<const half2*>(from);
0585 }
0586
0587 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu(const Eigen::half* from) {
0588 return combine_half(from[0], from[1]);
0589 }
0590
0591 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploaddup(const Eigen::half* from) {
0592 return combine_half(from[0], from[0]);
0593 }
0594
0595 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(Eigen::half* to,
0596 const half2& from) {
0597 *reinterpret_cast<half2*>(to) = from;
0598 }
0599
0600 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu(Eigen::half* to,
0601 const half2& from) {
0602 to[0] = get_half2_low(from);
0603 to[1] = get_half2_high(from);
0604 }
0605
0606
0607 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_aligned(
0608 const Eigen::half* from) {
0609 #if defined(EIGEN_GPU_HAS_LDG)
0610
0611 return __ldg(reinterpret_cast<const half2*>(from));
0612 #else
0613 return combine_half(*(from+0), *(from+1));
0614 #endif
0615 }
0616
0617 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_unaligned(
0618 const Eigen::half* from) {
0619 #if defined(EIGEN_GPU_HAS_LDG)
0620 return __halves2half2(__ldg(from+0), __ldg(from+1));
0621 #else
0622 return combine_half(*(from+0), *(from+1));
0623 #endif
0624 }
0625
0626 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pgather(const Eigen::half* from,
0627 Index stride) {
0628 return combine_half(from[0*stride], from[1*stride]);
0629 }
0630
0631 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter(
0632 Eigen::half* to, const half2& from, Index stride) {
0633 to[stride*0] = get_half2_low(from);
0634 to[stride*1] = get_half2_high(from);
0635 }
0636
0637 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& a) {
0638 return get_half2_low(a);
0639 }
0640
0641 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pabs(const half2& a) {
0642 half a1 = get_half2_low(a);
0643 half a2 = get_half2_high(a);
0644 half result1 = half_impl::raw_uint16_to_half(a1.x & 0x7FFF);
0645 half result2 = half_impl::raw_uint16_to_half(a2.x & 0x7FFF);
0646 return combine_half(result1, result2);
0647 }
0648
0649 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ptrue(const half2& ) {
0650 half true_half = half_impl::raw_uint16_to_half(0xffffu);
0651 return pset1<half2>(true_half);
0652 }
0653
0654 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pzero(const half2& ) {
0655 half false_half = half_impl::raw_uint16_to_half(0x0000u);
0656 return pset1<half2>(false_half);
0657 }
0658
0659 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
0660 ptranspose(PacketBlock<half2,2>& kernel) {
0661 __half a1 = get_half2_low(kernel.packet[0]);
0662 __half a2 = get_half2_high(kernel.packet[0]);
0663 __half b1 = get_half2_low(kernel.packet[1]);
0664 __half b2 = get_half2_high(kernel.packet[1]);
0665 kernel.packet[0] = combine_half(a1, b1);
0666 kernel.packet[1] = combine_half(a2, b2);
0667 }
0668
0669 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const Eigen::half& a) {
0670 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0671 return __halves2half2(a, __hadd(a, __float2half(1.0f)));
0672 #else
0673 float f = __half2float(a) + 1.0f;
0674 return combine_half(a, __float2half(f));
0675 #endif
0676 }
0677
0678 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pselect(const half2& mask,
0679 const half2& a,
0680 const half2& b) {
0681 half mask_low = get_half2_low(mask);
0682 half mask_high = get_half2_high(mask);
0683 half result_low = mask_low == half(0) ? get_half2_low(b) : get_half2_low(a);
0684 half result_high = mask_high == half(0) ? get_half2_high(b) : get_half2_high(a);
0685 return combine_half(result_low, result_high);
0686 }
0687
0688 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_eq(const half2& a,
0689 const half2& b) {
0690 half true_half = half_impl::raw_uint16_to_half(0xffffu);
0691 half false_half = half_impl::raw_uint16_to_half(0x0000u);
0692 half a1 = get_half2_low(a);
0693 half a2 = get_half2_high(a);
0694 half b1 = get_half2_low(b);
0695 half b2 = get_half2_high(b);
0696 half eq1 = __half2float(a1) == __half2float(b1) ? true_half : false_half;
0697 half eq2 = __half2float(a2) == __half2float(b2) ? true_half : false_half;
0698 return combine_half(eq1, eq2);
0699 }
0700
0701 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_lt(const half2& a,
0702 const half2& b) {
0703 half true_half = half_impl::raw_uint16_to_half(0xffffu);
0704 half false_half = half_impl::raw_uint16_to_half(0x0000u);
0705 half a1 = get_half2_low(a);
0706 half a2 = get_half2_high(a);
0707 half b1 = get_half2_low(b);
0708 half b2 = get_half2_high(b);
0709 half eq1 = __half2float(a1) < __half2float(b1) ? true_half : false_half;
0710 half eq2 = __half2float(a2) < __half2float(b2) ? true_half : false_half;
0711 return combine_half(eq1, eq2);
0712 }
0713
0714 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pand(const half2& a,
0715 const half2& b) {
0716 half a1 = get_half2_low(a);
0717 half a2 = get_half2_high(a);
0718 half b1 = get_half2_low(b);
0719 half b2 = get_half2_high(b);
0720 half result1 = half_impl::raw_uint16_to_half(a1.x & b1.x);
0721 half result2 = half_impl::raw_uint16_to_half(a2.x & b2.x);
0722 return combine_half(result1, result2);
0723 }
0724
0725 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 por(const half2& a,
0726 const half2& b) {
0727 half a1 = get_half2_low(a);
0728 half a2 = get_half2_high(a);
0729 half b1 = get_half2_low(b);
0730 half b2 = get_half2_high(b);
0731 half result1 = half_impl::raw_uint16_to_half(a1.x | b1.x);
0732 half result2 = half_impl::raw_uint16_to_half(a2.x | b2.x);
0733 return combine_half(result1, result2);
0734 }
0735
0736 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pxor(const half2& a,
0737 const half2& b) {
0738 half a1 = get_half2_low(a);
0739 half a2 = get_half2_high(a);
0740 half b1 = get_half2_low(b);
0741 half b2 = get_half2_high(b);
0742 half result1 = half_impl::raw_uint16_to_half(a1.x ^ b1.x);
0743 half result2 = half_impl::raw_uint16_to_half(a2.x ^ b2.x);
0744 return combine_half(result1, result2);
0745 }
0746
0747 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pandnot(const half2& a,
0748 const half2& b) {
0749 half a1 = get_half2_low(a);
0750 half a2 = get_half2_high(a);
0751 half b1 = get_half2_low(b);
0752 half b2 = get_half2_high(b);
0753 half result1 = half_impl::raw_uint16_to_half(a1.x & ~b1.x);
0754 half result2 = half_impl::raw_uint16_to_half(a2.x & ~b2.x);
0755 return combine_half(result1, result2);
0756 }
0757
0758 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd(const half2& a,
0759 const half2& b) {
0760 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0761 return __hadd2(a, b);
0762 #else
0763 float a1 = __low2float(a);
0764 float a2 = __high2float(a);
0765 float b1 = __low2float(b);
0766 float b2 = __high2float(b);
0767 float r1 = a1 + b1;
0768 float r2 = a2 + b2;
0769 return __floats2half2_rn(r1, r2);
0770 #endif
0771 }
0772
0773 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub(const half2& a,
0774 const half2& b) {
0775 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0776 return __hsub2(a, b);
0777 #else
0778 float a1 = __low2float(a);
0779 float a2 = __high2float(a);
0780 float b1 = __low2float(b);
0781 float b2 = __high2float(b);
0782 float r1 = a1 - b1;
0783 float r2 = a2 - b2;
0784 return __floats2half2_rn(r1, r2);
0785 #endif
0786 }
0787
0788 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
0789 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0790 return __hneg2(a);
0791 #else
0792 float a1 = __low2float(a);
0793 float a2 = __high2float(a);
0794 return __floats2half2_rn(-a1, -a2);
0795 #endif
0796 }
0797
0798 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; }
0799
0800 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul(const half2& a,
0801 const half2& b) {
0802 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0803 return __hmul2(a, b);
0804 #else
0805 float a1 = __low2float(a);
0806 float a2 = __high2float(a);
0807 float b1 = __low2float(b);
0808 float b2 = __high2float(b);
0809 float r1 = a1 * b1;
0810 float r2 = a2 * b2;
0811 return __floats2half2_rn(r1, r2);
0812 #endif
0813 }
0814
0815 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd(const half2& a,
0816 const half2& b,
0817 const half2& c) {
0818 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0819 return __hfma2(a, b, c);
0820 #else
0821 float a1 = __low2float(a);
0822 float a2 = __high2float(a);
0823 float b1 = __low2float(b);
0824 float b2 = __high2float(b);
0825 float c1 = __low2float(c);
0826 float c2 = __high2float(c);
0827 float r1 = a1 * b1 + c1;
0828 float r2 = a2 * b2 + c2;
0829 return __floats2half2_rn(r1, r2);
0830 #endif
0831 }
0832
0833 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv(const half2& a,
0834 const half2& b) {
0835 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0836 return __h2div(a, b);
0837 #else
0838 float a1 = __low2float(a);
0839 float a2 = __high2float(a);
0840 float b1 = __low2float(b);
0841 float b2 = __high2float(b);
0842 float r1 = a1 / b1;
0843 float r2 = a2 / b2;
0844 return __floats2half2_rn(r1, r2);
0845 #endif
0846 }
0847
0848 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin(const half2& a,
0849 const half2& b) {
0850 float a1 = __low2float(a);
0851 float a2 = __high2float(a);
0852 float b1 = __low2float(b);
0853 float b2 = __high2float(b);
0854 __half r1 = a1 < b1 ? get_half2_low(a) : get_half2_low(b);
0855 __half r2 = a2 < b2 ? get_half2_high(a) : get_half2_high(b);
0856 return combine_half(r1, r2);
0857 }
0858
0859 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a,
0860 const half2& b) {
0861 float a1 = __low2float(a);
0862 float a2 = __high2float(a);
0863 float b1 = __low2float(b);
0864 float b2 = __high2float(b);
0865 __half r1 = a1 > b1 ? get_half2_low(a) : get_half2_low(b);
0866 __half r2 = a2 > b2 ? get_half2_high(a) : get_half2_high(b);
0867 return combine_half(r1, r2);
0868 }
0869
0870 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux(const half2& a) {
0871 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0872 return __hadd(__low2half(a), __high2half(a));
0873 #else
0874 float a1 = __low2float(a);
0875 float a2 = __high2float(a);
0876 return Eigen::half(__float2half(a1 + a2));
0877 #endif
0878 }
0879
0880 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max(const half2& a) {
0881 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0882 __half first = __low2half(a);
0883 __half second = __high2half(a);
0884 return __hgt(first, second) ? first : second;
0885 #else
0886 float a1 = __low2float(a);
0887 float a2 = __high2float(a);
0888 return a1 > a2 ? get_half2_low(a) : get_half2_high(a);
0889 #endif
0890 }
0891
0892 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min(const half2& a) {
0893 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0894 __half first = __low2half(a);
0895 __half second = __high2half(a);
0896 return __hlt(first, second) ? first : second;
0897 #else
0898 float a1 = __low2float(a);
0899 float a2 = __high2float(a);
0900 return a1 < a2 ? get_half2_low(a) : get_half2_high(a);
0901 #endif
0902 }
0903
0904 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul(const half2& a) {
0905 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
0906 return __hmul(__low2half(a), __high2half(a));
0907 #else
0908 float a1 = __low2float(a);
0909 float a2 = __high2float(a);
0910 return Eigen::half(__float2half(a1 * a2));
0911 #endif
0912 }
0913
0914 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog1p(const half2& a) {
0915 float a1 = __low2float(a);
0916 float a2 = __high2float(a);
0917 float r1 = log1pf(a1);
0918 float r2 = log1pf(a2);
0919 return __floats2half2_rn(r1, r2);
0920 }
0921
0922 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexpm1(const half2& a) {
0923 float a1 = __low2float(a);
0924 float a2 = __high2float(a);
0925 float r1 = expm1f(a1);
0926 float r2 = expm1f(a2);
0927 return __floats2half2_rn(r1, r2);
0928 }
0929
0930 #if (EIGEN_CUDA_SDK_VER >= 80000 && defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)) || \
0931 defined(EIGEN_HIP_DEVICE_COMPILE)
0932
0933 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0934 half2 plog(const half2& a) {
0935 return h2log(a);
0936 }
0937
0938 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0939 half2 pexp(const half2& a) {
0940 return h2exp(a);
0941 }
0942
0943 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0944 half2 psqrt(const half2& a) {
0945 return h2sqrt(a);
0946 }
0947
0948 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0949 half2 prsqrt(const half2& a) {
0950 return h2rsqrt(a);
0951 }
0952
0953 #else
0954
0955 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog(const half2& a) {
0956 float a1 = __low2float(a);
0957 float a2 = __high2float(a);
0958 float r1 = logf(a1);
0959 float r2 = logf(a2);
0960 return __floats2half2_rn(r1, r2);
0961 }
0962
0963 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp(const half2& a) {
0964 float a1 = __low2float(a);
0965 float a2 = __high2float(a);
0966 float r1 = expf(a1);
0967 float r2 = expf(a2);
0968 return __floats2half2_rn(r1, r2);
0969 }
0970
0971 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt(const half2& a) {
0972 float a1 = __low2float(a);
0973 float a2 = __high2float(a);
0974 float r1 = sqrtf(a1);
0975 float r2 = sqrtf(a2);
0976 return __floats2half2_rn(r1, r2);
0977 }
0978
0979 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt(const half2& a) {
0980 float a1 = __low2float(a);
0981 float a2 = __high2float(a);
0982 float r1 = rsqrtf(a1);
0983 float r2 = rsqrtf(a2);
0984 return __floats2half2_rn(r1, r2);
0985 }
0986 #endif
0987 }
0988
0989 template <>
0990 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
0991 pload<Packet4h2>(const Eigen::half* from) {
0992 return *reinterpret_cast<const Packet4h2*>(from);
0993 }
0994
0995
0996 template <>
0997 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
0998 ploadu<Packet4h2>(const Eigen::half* from) {
0999 Packet4h2 r;
1000 half2* p_alias = reinterpret_cast<half2*>(&r);
1001 p_alias[0] = ploadu(from + 0);
1002 p_alias[1] = ploadu(from + 2);
1003 p_alias[2] = ploadu(from + 4);
1004 p_alias[3] = ploadu(from + 6);
1005 return r;
1006 }
1007
1008 template <>
1009 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1010 ploaddup<Packet4h2>(const Eigen::half* from) {
1011 Packet4h2 r;
1012 half2* p_alias = reinterpret_cast<half2*>(&r);
1013 p_alias[0] = ploaddup(from + 0);
1014 p_alias[1] = ploaddup(from + 1);
1015 p_alias[2] = ploaddup(from + 2);
1016 p_alias[3] = ploaddup(from + 3);
1017 return r;
1018 }
1019
1020 template <>
1021 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<Eigen::half>(
1022 Eigen::half* to, const Packet4h2& from) {
1023 *reinterpret_cast<Packet4h2*>(to) = from;
1024 }
1025
1026 template <>
1027 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(
1028 Eigen::half* to, const Packet4h2& from) {
1029 const half2* from_alias = reinterpret_cast<const half2*>(&from);
1030 pstoreu(to + 0,from_alias[0]);
1031 pstoreu(to + 2,from_alias[1]);
1032 pstoreu(to + 4,from_alias[2]);
1033 pstoreu(to + 6,from_alias[3]);
1034 }
1035
1036 template <>
1037 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2
1038 ploadt_ro<Packet4h2, Aligned>(const Eigen::half* from) {
1039 #if defined(EIGEN_GPU_HAS_LDG)
1040 Packet4h2 r;
1041 r = __ldg(reinterpret_cast<const Packet4h2*>(from));
1042 return r;
1043 #else
1044 Packet4h2 r;
1045 half2* r_alias = reinterpret_cast<half2*>(&r);
1046 r_alias[0] = ploadt_ro_aligned(from + 0);
1047 r_alias[1] = ploadt_ro_aligned(from + 2);
1048 r_alias[2] = ploadt_ro_aligned(from + 4);
1049 r_alias[3] = ploadt_ro_aligned(from + 6);
1050 return r;
1051 #endif
1052 }
1053
1054 template <>
1055 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2
1056 ploadt_ro<Packet4h2, Unaligned>(const Eigen::half* from) {
1057 Packet4h2 r;
1058 half2* r_alias = reinterpret_cast<half2*>(&r);
1059 r_alias[0] = ploadt_ro_unaligned(from + 0);
1060 r_alias[1] = ploadt_ro_unaligned(from + 2);
1061 r_alias[2] = ploadt_ro_unaligned(from + 4);
1062 r_alias[3] = ploadt_ro_unaligned(from + 6);
1063 return r;
1064 }
1065
1066 template <>
1067 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1068 pgather<Eigen::half, Packet4h2>(const Eigen::half* from, Index stride) {
1069 Packet4h2 r;
1070 half2* p_alias = reinterpret_cast<half2*>(&r);
1071 p_alias[0] = combine_half(from[0 * stride], from[1 * stride]);
1072 p_alias[1] = combine_half(from[2 * stride], from[3 * stride]);
1073 p_alias[2] = combine_half(from[4 * stride], from[5 * stride]);
1074 p_alias[3] = combine_half(from[6 * stride], from[7 * stride]);
1075 return r;
1076 }
1077
1078 template <>
1079 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet4h2>(
1080 Eigen::half* to, const Packet4h2& from, Index stride) {
1081 const half2* from_alias = reinterpret_cast<const half2*>(&from);
1082 pscatter(to + stride * 0, from_alias[0], stride);
1083 pscatter(to + stride * 2, from_alias[1], stride);
1084 pscatter(to + stride * 4, from_alias[2], stride);
1085 pscatter(to + stride * 6, from_alias[3], stride);
1086 }
1087
1088 template <>
1089 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst<Packet4h2>(
1090 const Packet4h2& a) {
1091 return pfirst(*(reinterpret_cast<const half2*>(&a)));
1092 }
1093
1094 template <>
1095 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pabs<Packet4h2>(
1096 const Packet4h2& a) {
1097 Packet4h2 r;
1098 half2* p_alias = reinterpret_cast<half2*>(&r);
1099 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1100 p_alias[0] = pabs(a_alias[0]);
1101 p_alias[1] = pabs(a_alias[1]);
1102 p_alias[2] = pabs(a_alias[2]);
1103 p_alias[3] = pabs(a_alias[3]);
1104 return r;
1105 }
1106
1107 template <>
1108 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 ptrue<Packet4h2>(
1109 const Packet4h2& ) {
1110 half true_half = half_impl::raw_uint16_to_half(0xffffu);
1111 return pset1<Packet4h2>(true_half);
1112 }
1113
1114 template <>
1115 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pzero<Packet4h2>(const Packet4h2& ) {
1116 half false_half = half_impl::raw_uint16_to_half(0x0000u);
1117 return pset1<Packet4h2>(false_half);
1118 }
1119
1120 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_double(
1121 double* d_row0, double* d_row1, double* d_row2, double* d_row3,
1122 double* d_row4, double* d_row5, double* d_row6, double* d_row7) {
1123 double d_tmp;
1124 d_tmp = d_row0[1];
1125 d_row0[1] = d_row4[0];
1126 d_row4[0] = d_tmp;
1127
1128 d_tmp = d_row1[1];
1129 d_row1[1] = d_row5[0];
1130 d_row5[0] = d_tmp;
1131
1132 d_tmp = d_row2[1];
1133 d_row2[1] = d_row6[0];
1134 d_row6[0] = d_tmp;
1135
1136 d_tmp = d_row3[1];
1137 d_row3[1] = d_row7[0];
1138 d_row7[0] = d_tmp;
1139 }
1140
1141 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_half2(
1142 half2* f_row0, half2* f_row1, half2* f_row2, half2* f_row3) {
1143 half2 f_tmp;
1144 f_tmp = f_row0[1];
1145 f_row0[1] = f_row2[0];
1146 f_row2[0] = f_tmp;
1147
1148 f_tmp = f_row1[1];
1149 f_row1[1] = f_row3[0];
1150 f_row3[0] = f_tmp;
1151 }
1152
1153 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
1154 ptranspose_half(half2& f0, half2& f1) {
1155 __half a1 = get_half2_low(f0);
1156 __half a2 = get_half2_high(f0);
1157 __half b1 = get_half2_low(f1);
1158 __half b2 = get_half2_high(f1);
1159 f0 = combine_half(a1, b1);
1160 f1 = combine_half(a2, b2);
1161 }
1162
1163 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
1164 ptranspose(PacketBlock<Packet4h2,8>& kernel) {
1165 double* d_row0 = reinterpret_cast<double*>(&kernel.packet[0]);
1166 double* d_row1 = reinterpret_cast<double*>(&kernel.packet[1]);
1167 double* d_row2 = reinterpret_cast<double*>(&kernel.packet[2]);
1168 double* d_row3 = reinterpret_cast<double*>(&kernel.packet[3]);
1169 double* d_row4 = reinterpret_cast<double*>(&kernel.packet[4]);
1170 double* d_row5 = reinterpret_cast<double*>(&kernel.packet[5]);
1171 double* d_row6 = reinterpret_cast<double*>(&kernel.packet[6]);
1172 double* d_row7 = reinterpret_cast<double*>(&kernel.packet[7]);
1173 ptranspose_double(d_row0, d_row1, d_row2, d_row3,
1174 d_row4, d_row5, d_row6, d_row7);
1175
1176
1177 half2* f_row0 = reinterpret_cast<half2*>(d_row0);
1178 half2* f_row1 = reinterpret_cast<half2*>(d_row1);
1179 half2* f_row2 = reinterpret_cast<half2*>(d_row2);
1180 half2* f_row3 = reinterpret_cast<half2*>(d_row3);
1181 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1182 ptranspose_half(f_row0[0], f_row1[0]);
1183 ptranspose_half(f_row0[1], f_row1[1]);
1184 ptranspose_half(f_row2[0], f_row3[0]);
1185 ptranspose_half(f_row2[1], f_row3[1]);
1186
1187 f_row0 = reinterpret_cast<half2*>(d_row0 + 1);
1188 f_row1 = reinterpret_cast<half2*>(d_row1 + 1);
1189 f_row2 = reinterpret_cast<half2*>(d_row2 + 1);
1190 f_row3 = reinterpret_cast<half2*>(d_row3 + 1);
1191 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1192 ptranspose_half(f_row0[0], f_row1[0]);
1193 ptranspose_half(f_row0[1], f_row1[1]);
1194 ptranspose_half(f_row2[0], f_row3[0]);
1195 ptranspose_half(f_row2[1], f_row3[1]);
1196
1197 f_row0 = reinterpret_cast<half2*>(d_row4);
1198 f_row1 = reinterpret_cast<half2*>(d_row5);
1199 f_row2 = reinterpret_cast<half2*>(d_row6);
1200 f_row3 = reinterpret_cast<half2*>(d_row7);
1201 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1202 ptranspose_half(f_row0[0], f_row1[0]);
1203 ptranspose_half(f_row0[1], f_row1[1]);
1204 ptranspose_half(f_row2[0], f_row3[0]);
1205 ptranspose_half(f_row2[1], f_row3[1]);
1206
1207 f_row0 = reinterpret_cast<half2*>(d_row4 + 1);
1208 f_row1 = reinterpret_cast<half2*>(d_row5 + 1);
1209 f_row2 = reinterpret_cast<half2*>(d_row6 + 1);
1210 f_row3 = reinterpret_cast<half2*>(d_row7 + 1);
1211 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1212 ptranspose_half(f_row0[0], f_row1[0]);
1213 ptranspose_half(f_row0[1], f_row1[1]);
1214 ptranspose_half(f_row2[0], f_row3[0]);
1215 ptranspose_half(f_row2[1], f_row3[1]);
1216
1217 }
1218
1219 template <>
1220 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1221 plset<Packet4h2>(const Eigen::half& a) {
1222 #if defined(EIGEN_HIP_DEVICE_COMPILE)
1223
1224 Packet4h2 r;
1225 half2* p_alias = reinterpret_cast<half2*>(&r);
1226 p_alias[0] = __halves2half2(a, __hadd(a, __float2half(1.0f)));
1227 p_alias[1] = __halves2half2(__hadd(a, __float2half(2.0f)),
1228 __hadd(a, __float2half(3.0f)));
1229 p_alias[2] = __halves2half2(__hadd(a, __float2half(4.0f)),
1230 __hadd(a, __float2half(5.0f)));
1231 p_alias[3] = __halves2half2(__hadd(a, __float2half(6.0f)),
1232 __hadd(a, __float2half(7.0f)));
1233 return r;
1234 #elif defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1235 Packet4h2 r;
1236 half2* r_alias = reinterpret_cast<half2*>(&r);
1237
1238 half2 b = pset1<half2>(a);
1239 half2 c;
1240 half2 half_offset0 = __halves2half2(__float2half(0.0f),__float2half(2.0f));
1241 half2 half_offset1 = __halves2half2(__float2half(4.0f),__float2half(6.0f));
1242
1243 c = __hadd2(b, half_offset0);
1244 r_alias[0] = plset(__low2half(c));
1245 r_alias[1] = plset(__high2half(c));
1246
1247 c = __hadd2(b, half_offset1);
1248 r_alias[2] = plset(__low2half(c));
1249 r_alias[3] = plset(__high2half(c));
1250
1251 return r;
1252
1253 #else
1254 float f = __half2float(a);
1255 Packet4h2 r;
1256 half2* p_alias = reinterpret_cast<half2*>(&r);
1257 p_alias[0] = combine_half(a, __float2half(f + 1.0f));
1258 p_alias[1] = combine_half(__float2half(f + 2.0f), __float2half(f + 3.0f));
1259 p_alias[2] = combine_half(__float2half(f + 4.0f), __float2half(f + 5.0f));
1260 p_alias[3] = combine_half(__float2half(f + 6.0f), __float2half(f + 7.0f));
1261 return r;
1262 #endif
1263 }
1264
1265 template <>
1266 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1267 pselect<Packet4h2>(const Packet4h2& mask, const Packet4h2& a,
1268 const Packet4h2& b) {
1269 Packet4h2 r;
1270 half2* r_alias = reinterpret_cast<half2*>(&r);
1271 const half2* mask_alias = reinterpret_cast<const half2*>(&mask);
1272 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1273 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1274 r_alias[0] = pselect(mask_alias[0], a_alias[0], b_alias[0]);
1275 r_alias[1] = pselect(mask_alias[1], a_alias[1], b_alias[1]);
1276 r_alias[2] = pselect(mask_alias[2], a_alias[2], b_alias[2]);
1277 r_alias[3] = pselect(mask_alias[3], a_alias[3], b_alias[3]);
1278 return r;
1279 }
1280
1281 template <>
1282 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1283 pcmp_eq<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
1284 Packet4h2 r;
1285 half2* r_alias = reinterpret_cast<half2*>(&r);
1286 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1287 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1288 r_alias[0] = pcmp_eq(a_alias[0], b_alias[0]);
1289 r_alias[1] = pcmp_eq(a_alias[1], b_alias[1]);
1290 r_alias[2] = pcmp_eq(a_alias[2], b_alias[2]);
1291 r_alias[3] = pcmp_eq(a_alias[3], b_alias[3]);
1292 return r;
1293 }
1294
1295 template <>
1296 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pand<Packet4h2>(
1297 const Packet4h2& a, const Packet4h2& b) {
1298 Packet4h2 r;
1299 half2* r_alias = reinterpret_cast<half2*>(&r);
1300 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1301 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1302 r_alias[0] = pand(a_alias[0], b_alias[0]);
1303 r_alias[1] = pand(a_alias[1], b_alias[1]);
1304 r_alias[2] = pand(a_alias[2], b_alias[2]);
1305 r_alias[3] = pand(a_alias[3], b_alias[3]);
1306 return r;
1307 }
1308
1309 template <>
1310 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 por<Packet4h2>(
1311 const Packet4h2& a, const Packet4h2& b) {
1312 Packet4h2 r;
1313 half2* r_alias = reinterpret_cast<half2*>(&r);
1314 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1315 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1316 r_alias[0] = por(a_alias[0], b_alias[0]);
1317 r_alias[1] = por(a_alias[1], b_alias[1]);
1318 r_alias[2] = por(a_alias[2], b_alias[2]);
1319 r_alias[3] = por(a_alias[3], b_alias[3]);
1320 return r;
1321 }
1322
1323 template <>
1324 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pxor<Packet4h2>(
1325 const Packet4h2& a, const Packet4h2& b) {
1326 Packet4h2 r;
1327 half2* r_alias = reinterpret_cast<half2*>(&r);
1328 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1329 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1330 r_alias[0] = pxor(a_alias[0], b_alias[0]);
1331 r_alias[1] = pxor(a_alias[1], b_alias[1]);
1332 r_alias[2] = pxor(a_alias[2], b_alias[2]);
1333 r_alias[3] = pxor(a_alias[3], b_alias[3]);
1334 return r;
1335 }
1336
1337 template <>
1338 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1339 pandnot<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
1340 Packet4h2 r;
1341 half2* r_alias = reinterpret_cast<half2*>(&r);
1342 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1343 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1344 r_alias[0] = pandnot(a_alias[0], b_alias[0]);
1345 r_alias[1] = pandnot(a_alias[1], b_alias[1]);
1346 r_alias[2] = pandnot(a_alias[2], b_alias[2]);
1347 r_alias[3] = pandnot(a_alias[3], b_alias[3]);
1348 return r;
1349 }
1350
1351 template <>
1352 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 padd<Packet4h2>(
1353 const Packet4h2& a, const Packet4h2& b) {
1354 Packet4h2 r;
1355 half2* r_alias = reinterpret_cast<half2*>(&r);
1356 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1357 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1358 r_alias[0] = padd(a_alias[0], b_alias[0]);
1359 r_alias[1] = padd(a_alias[1], b_alias[1]);
1360 r_alias[2] = padd(a_alias[2], b_alias[2]);
1361 r_alias[3] = padd(a_alias[3], b_alias[3]);
1362 return r;
1363 }
1364
1365 template <>
1366 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psub<Packet4h2>(
1367 const Packet4h2& a, const Packet4h2& b) {
1368 Packet4h2 r;
1369 half2* r_alias = reinterpret_cast<half2*>(&r);
1370 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1371 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1372 r_alias[0] = psub(a_alias[0], b_alias[0]);
1373 r_alias[1] = psub(a_alias[1], b_alias[1]);
1374 r_alias[2] = psub(a_alias[2], b_alias[2]);
1375 r_alias[3] = psub(a_alias[3], b_alias[3]);
1376 return r;
1377 }
1378
1379 template <>
1380 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pnegate(const Packet4h2& a) {
1381 Packet4h2 r;
1382 half2* r_alias = reinterpret_cast<half2*>(&r);
1383 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1384 r_alias[0] = pnegate(a_alias[0]);
1385 r_alias[1] = pnegate(a_alias[1]);
1386 r_alias[2] = pnegate(a_alias[2]);
1387 r_alias[3] = pnegate(a_alias[3]);
1388 return r;
1389 }
1390
1391 template <>
1392 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pconj(const Packet4h2& a) {
1393 return a;
1394 }
1395
1396 template <>
1397 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmul<Packet4h2>(
1398 const Packet4h2& a, const Packet4h2& b) {
1399 Packet4h2 r;
1400 half2* r_alias = reinterpret_cast<half2*>(&r);
1401 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1402 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1403 r_alias[0] = pmul(a_alias[0], b_alias[0]);
1404 r_alias[1] = pmul(a_alias[1], b_alias[1]);
1405 r_alias[2] = pmul(a_alias[2], b_alias[2]);
1406 r_alias[3] = pmul(a_alias[3], b_alias[3]);
1407 return r;
1408 }
1409
1410 template <>
1411 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmadd<Packet4h2>(
1412 const Packet4h2& a, const Packet4h2& b, const Packet4h2& c) {
1413 Packet4h2 r;
1414 half2* r_alias = reinterpret_cast<half2*>(&r);
1415 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1416 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1417 const half2* c_alias = reinterpret_cast<const half2*>(&c);
1418 r_alias[0] = pmadd(a_alias[0], b_alias[0], c_alias[0]);
1419 r_alias[1] = pmadd(a_alias[1], b_alias[1], c_alias[1]);
1420 r_alias[2] = pmadd(a_alias[2], b_alias[2], c_alias[2]);
1421 r_alias[3] = pmadd(a_alias[3], b_alias[3], c_alias[3]);
1422 return r;
1423 }
1424
1425 template <>
1426 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pdiv<Packet4h2>(
1427 const Packet4h2& a, const Packet4h2& b) {
1428 Packet4h2 r;
1429 half2* r_alias = reinterpret_cast<half2*>(&r);
1430 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1431 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1432 r_alias[0] = pdiv(a_alias[0], b_alias[0]);
1433 r_alias[1] = pdiv(a_alias[1], b_alias[1]);
1434 r_alias[2] = pdiv(a_alias[2], b_alias[2]);
1435 r_alias[3] = pdiv(a_alias[3], b_alias[3]);
1436 return r;
1437 }
1438
1439 template <>
1440 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmin<Packet4h2>(
1441 const Packet4h2& a, const Packet4h2& b) {
1442 Packet4h2 r;
1443 half2* r_alias = reinterpret_cast<half2*>(&r);
1444 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1445 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1446 r_alias[0] = pmin(a_alias[0], b_alias[0]);
1447 r_alias[1] = pmin(a_alias[1], b_alias[1]);
1448 r_alias[2] = pmin(a_alias[2], b_alias[2]);
1449 r_alias[3] = pmin(a_alias[3], b_alias[3]);
1450 return r;
1451 }
1452
1453 template <>
1454 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmax<Packet4h2>(
1455 const Packet4h2& a, const Packet4h2& b) {
1456 Packet4h2 r;
1457 half2* r_alias = reinterpret_cast<half2*>(&r);
1458 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1459 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1460 r_alias[0] = pmax(a_alias[0], b_alias[0]);
1461 r_alias[1] = pmax(a_alias[1], b_alias[1]);
1462 r_alias[2] = pmax(a_alias[2], b_alias[2]);
1463 r_alias[3] = pmax(a_alias[3], b_alias[3]);
1464 return r;
1465 }
1466
1467 template <>
1468 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<Packet4h2>(
1469 const Packet4h2& a) {
1470 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1471
1472 return predux(a_alias[0]) + predux(a_alias[1]) +
1473 predux(a_alias[2]) + predux(a_alias[3]);
1474 }
1475
1476 template <>
1477 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<Packet4h2>(
1478 const Packet4h2& a) {
1479 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1480 half2 m0 = combine_half(predux_max(a_alias[0]),
1481 predux_max(a_alias[1]));
1482 half2 m1 = combine_half(predux_max(a_alias[2]),
1483 predux_max(a_alias[3]));
1484 __half first = predux_max(m0);
1485 __half second = predux_max(m1);
1486 #if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1487 return (__hgt(first, second) ? first : second);
1488 #else
1489 float ffirst = __half2float(first);
1490 float fsecond = __half2float(second);
1491 return (ffirst > fsecond)? first: second;
1492 #endif
1493 }
1494
1495 template <>
1496 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<Packet4h2>(
1497 const Packet4h2& a) {
1498 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1499 half2 m0 = combine_half(predux_min(a_alias[0]),
1500 predux_min(a_alias[1]));
1501 half2 m1 = combine_half(predux_min(a_alias[2]),
1502 predux_min(a_alias[3]));
1503 __half first = predux_min(m0);
1504 __half second = predux_min(m1);
1505 #if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1506 return (__hlt(first, second) ? first : second);
1507 #else
1508 float ffirst = __half2float(first);
1509 float fsecond = __half2float(second);
1510 return (ffirst < fsecond)? first: second;
1511 #endif
1512 }
1513
1514
1515 template <>
1516 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet4h2>(
1517 const Packet4h2& a) {
1518 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1519 return predux_mul(pmul(pmul(a_alias[0], a_alias[1]),
1520 pmul(a_alias[2], a_alias[3])));
1521 }
1522
1523 template <>
1524 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1525 plog1p<Packet4h2>(const Packet4h2& a) {
1526 Packet4h2 r;
1527 half2* r_alias = reinterpret_cast<half2*>(&r);
1528 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1529 r_alias[0] = plog1p(a_alias[0]);
1530 r_alias[1] = plog1p(a_alias[1]);
1531 r_alias[2] = plog1p(a_alias[2]);
1532 r_alias[3] = plog1p(a_alias[3]);
1533 return r;
1534 }
1535
1536 template <>
1537 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1538 pexpm1<Packet4h2>(const Packet4h2& a) {
1539 Packet4h2 r;
1540 half2* r_alias = reinterpret_cast<half2*>(&r);
1541 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1542 r_alias[0] = pexpm1(a_alias[0]);
1543 r_alias[1] = pexpm1(a_alias[1]);
1544 r_alias[2] = pexpm1(a_alias[2]);
1545 r_alias[3] = pexpm1(a_alias[3]);
1546 return r;
1547 }
1548
1549 template <>
1550 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 plog<Packet4h2>(const Packet4h2& a) {
1551 Packet4h2 r;
1552 half2* r_alias = reinterpret_cast<half2*>(&r);
1553 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1554 r_alias[0] = plog(a_alias[0]);
1555 r_alias[1] = plog(a_alias[1]);
1556 r_alias[2] = plog(a_alias[2]);
1557 r_alias[3] = plog(a_alias[3]);
1558 return r;
1559 }
1560
1561 template <>
1562 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pexp<Packet4h2>(const Packet4h2& a) {
1563 Packet4h2 r;
1564 half2* r_alias = reinterpret_cast<half2*>(&r);
1565 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1566 r_alias[0] = pexp(a_alias[0]);
1567 r_alias[1] = pexp(a_alias[1]);
1568 r_alias[2] = pexp(a_alias[2]);
1569 r_alias[3] = pexp(a_alias[3]);
1570 return r;
1571 }
1572
1573 template <>
1574 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psqrt<Packet4h2>(const Packet4h2& a) {
1575 Packet4h2 r;
1576 half2* r_alias = reinterpret_cast<half2*>(&r);
1577 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1578 r_alias[0] = psqrt(a_alias[0]);
1579 r_alias[1] = psqrt(a_alias[1]);
1580 r_alias[2] = psqrt(a_alias[2]);
1581 r_alias[3] = psqrt(a_alias[3]);
1582 return r;
1583 }
1584
1585 template <>
1586 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1587 prsqrt<Packet4h2>(const Packet4h2& a) {
1588 Packet4h2 r;
1589 half2* r_alias = reinterpret_cast<half2*>(&r);
1590 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1591 r_alias[0] = prsqrt(a_alias[0]);
1592 r_alias[1] = prsqrt(a_alias[1]);
1593 r_alias[2] = prsqrt(a_alias[2]);
1594 r_alias[3] = prsqrt(a_alias[3]);
1595 return r;
1596 }
1597
1598
1599
1600 template<>
1601 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2& a,
1602 const half2& b) {
1603 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1604 return __hadd2(a, b);
1605 #else
1606 float a1 = __low2float(a);
1607 float a2 = __high2float(a);
1608 float b1 = __low2float(b);
1609 float b2 = __high2float(b);
1610 float r1 = a1 + b1;
1611 float r2 = a2 + b2;
1612 return __floats2half2_rn(r1, r2);
1613 #endif
1614 }
1615
1616 template<>
1617 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2& a,
1618 const half2& b) {
1619 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1620 return __hmul2(a, b);
1621 #else
1622 float a1 = __low2float(a);
1623 float a2 = __high2float(a);
1624 float b1 = __low2float(b);
1625 float b2 = __high2float(b);
1626 float r1 = a1 * b1;
1627 float r2 = a2 * b2;
1628 return __floats2half2_rn(r1, r2);
1629 #endif
1630 }
1631
1632 template<>
1633 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2& a,
1634 const half2& b) {
1635 #if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1636 return __h2div(a, b);
1637 #else
1638 float a1 = __low2float(a);
1639 float a2 = __high2float(a);
1640 float b1 = __low2float(b);
1641 float b2 = __high2float(b);
1642 float r1 = a1 / b1;
1643 float r2 = a2 / b2;
1644 return __floats2half2_rn(r1, r2);
1645 #endif
1646 }
1647
1648 template<>
1649 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a,
1650 const half2& b) {
1651 float a1 = __low2float(a);
1652 float a2 = __high2float(a);
1653 float b1 = __low2float(b);
1654 float b2 = __high2float(b);
1655 __half r1 = a1 < b1 ? get_half2_low(a) : get_half2_low(b);
1656 __half r2 = a2 < b2 ? get_half2_high(a) : get_half2_high(b);
1657 return combine_half(r1, r2);
1658 }
1659
1660 template<>
1661 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a,
1662 const half2& b) {
1663 float a1 = __low2float(a);
1664 float a2 = __high2float(a);
1665 float b1 = __low2float(b);
1666 float b2 = __high2float(b);
1667 __half r1 = a1 > b1 ? get_half2_low(a) : get_half2_low(b);
1668 __half r2 = a2 > b2 ? get_half2_high(a) : get_half2_high(b);
1669 return combine_half(r1, r2);
1670 }
1671
1672
1673
1674 #endif
1675
1676 #undef EIGEN_GPU_HAS_LDG
1677 #undef EIGEN_CUDA_HAS_FP16_ARITHMETIC
1678 #undef EIGEN_GPU_HAS_FP16_ARITHMETIC
1679
1680 }
1681
1682 }
1683
1684
1685 #endif