RavEngine
Loading...
Searching...
No Matches
PacketMath.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_PACKET_MATH_GPU_H
11#define EIGEN_PACKET_MATH_GPU_H
12
13namespace Eigen {
14
15namespace internal {
16
17// Read-only data cached load available.
18#if defined(EIGEN_HIP_DEVICE_COMPILE) || (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 350)
19#define EIGEN_GPU_HAS_LDG 1
20#endif
21
22// FP16 math available.
23#if (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530)
24#define EIGEN_CUDA_HAS_FP16_ARITHMETIC 1
25#endif
26
27#if defined(EIGEN_HIP_DEVICE_COMPILE) || defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
28#define EIGEN_GPU_HAS_FP16_ARITHMETIC 1
29#endif
30
31// Make sure this is only available when targeting a GPU: we don't want to
32// introduce conflicts between these packet_traits definitions and the ones
33// we'll use on the host side (SSE, AVX, ...)
34#if defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
35
36template<> struct is_arithmetic<float4> { enum { value = true }; };
37template<> struct is_arithmetic<double2> { enum { value = true }; };
38
39template<> struct packet_traits<float> : default_packet_traits
40{
41 typedef float4 type;
42 typedef float4 half;
43 enum {
44 Vectorizable = 1,
45 AlignedOnScalar = 1,
46 size=4,
47 HasHalfPacket = 0,
48
49 HasDiv = 1,
50 HasSin = 0,
51 HasCos = 0,
52 HasLog = 1,
53 HasExp = 1,
54 HasSqrt = 1,
55 HasRsqrt = 1,
56 HasLGamma = 1,
57 HasDiGamma = 1,
58 HasZeta = 1,
59 HasPolygamma = 1,
60 HasErf = 1,
61 HasErfc = 1,
62 HasNdtri = 1,
63 HasBessel = 1,
64 HasIGamma = 1,
65 HasIGammaDerA = 1,
66 HasGammaSampleDerAlpha = 1,
67 HasIGammac = 1,
68 HasBetaInc = 1,
69
70 HasBlend = 0,
71 HasFloor = 1,
72 };
73};
74
75template<> struct packet_traits<double> : default_packet_traits
76{
77 typedef double2 type;
78 typedef double2 half;
79 enum {
80 Vectorizable = 1,
81 AlignedOnScalar = 1,
82 size=2,
83 HasHalfPacket = 0,
84
85 HasDiv = 1,
86 HasLog = 1,
87 HasExp = 1,
88 HasSqrt = 1,
89 HasRsqrt = 1,
90 HasLGamma = 1,
91 HasDiGamma = 1,
92 HasZeta = 1,
93 HasPolygamma = 1,
94 HasErf = 1,
95 HasErfc = 1,
96 HasNdtri = 1,
97 HasBessel = 1,
98 HasIGamma = 1,
99 HasIGammaDerA = 1,
100 HasGammaSampleDerAlpha = 1,
101 HasIGammac = 1,
102 HasBetaInc = 1,
103
104 HasBlend = 0,
105 HasFloor = 1,
106 };
107};
108
109
110template<> 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; };
111template<> 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; };
112
113template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pset1<float4>(const float& from) {
114 return make_float4(from, from, from, from);
115}
116template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pset1<double2>(const double& from) {
117 return make_double2(from, from);
118}
119
120// We need to distinguish ‘clang as the CUDA compiler’ from ‘clang as the host compiler,
121// invoked by NVCC’ (e.g. on MacOS). The former needs to see both host and device implementation
122// of the functions, while the latter can only deal with one of them.
123#if defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
124namespace {
125
126EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_and(const float& a,
127 const float& b) {
128 return __int_as_float(__float_as_int(a) & __float_as_int(b));
129}
130EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_and(const double& a,
131 const double& b) {
132 return __longlong_as_double(__double_as_longlong(a) &
133 __double_as_longlong(b));
134}
135
136EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_or(const float& a,
137 const float& b) {
138 return __int_as_float(__float_as_int(a) | __float_as_int(b));
139}
140EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_or(const double& a,
141 const double& b) {
142 return __longlong_as_double(__double_as_longlong(a) |
143 __double_as_longlong(b));
144}
145
146EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_xor(const float& a,
147 const float& b) {
148 return __int_as_float(__float_as_int(a) ^ __float_as_int(b));
149}
150EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_xor(const double& a,
151 const double& b) {
152 return __longlong_as_double(__double_as_longlong(a) ^
153 __double_as_longlong(b));
154}
155
156EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_andnot(const float& a,
157 const float& b) {
158 return __int_as_float(__float_as_int(a) & ~__float_as_int(b));
159}
160EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_andnot(const double& a,
161 const double& b) {
162 return __longlong_as_double(__double_as_longlong(a) &
163 ~__double_as_longlong(b));
164}
165EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float eq_mask(const float& a,
166 const float& b) {
167 return __int_as_float(a == b ? 0xffffffffu : 0u);
168}
169EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double eq_mask(const double& a,
170 const double& b) {
171 return __longlong_as_double(a == b ? 0xffffffffffffffffull : 0ull);
172}
173
174EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float lt_mask(const float& a,
175 const float& b) {
176 return __int_as_float(a < b ? 0xffffffffu : 0u);
177}
178EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double lt_mask(const double& a,
179 const double& b) {
180 return __longlong_as_double(a < b ? 0xffffffffffffffffull : 0ull);
181}
182
183} // namespace
184
185template <>
186EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pand<float4>(const float4& a,
187 const float4& b) {
188 return make_float4(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y),
189 bitwise_and(a.z, b.z), bitwise_and(a.w, b.w));
190}
191template <>
192EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pand<double2>(const double2& a,
193 const double2& b) {
194 return make_double2(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y));
195}
196
197template <>
198EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 por<float4>(const float4& a,
199 const float4& b) {
200 return make_float4(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y),
201 bitwise_or(a.z, b.z), bitwise_or(a.w, b.w));
202}
203template <>
204EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 por<double2>(const double2& a,
205 const double2& b) {
206 return make_double2(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y));
207}
208
209template <>
210EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pxor<float4>(const float4& a,
211 const float4& b) {
212 return make_float4(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y),
213 bitwise_xor(a.z, b.z), bitwise_xor(a.w, b.w));
214}
215template <>
216EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pxor<double2>(const double2& a,
217 const double2& b) {
218 return make_double2(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y));
219}
220
221template <>
222EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pandnot<float4>(const float4& a,
223 const float4& b) {
224 return make_float4(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y),
225 bitwise_andnot(a.z, b.z), bitwise_andnot(a.w, b.w));
226}
227template <>
228EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
229pandnot<double2>(const double2& a, const double2& b) {
230 return make_double2(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y));
231}
232
233template <>
234EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_eq<float4>(const float4& a,
235 const float4& b) {
236 return make_float4(eq_mask(a.x, b.x), eq_mask(a.y, b.y), eq_mask(a.z, b.z),
237 eq_mask(a.w, b.w));
238}
239template <>
240EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_lt<float4>(const float4& a,
241 const float4& b) {
242 return make_float4(lt_mask(a.x, b.x), lt_mask(a.y, b.y), lt_mask(a.z, b.z),
243 lt_mask(a.w, b.w));
244}
245template <>
246EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
247pcmp_eq<double2>(const double2& a, const double2& b) {
248 return make_double2(eq_mask(a.x, b.x), eq_mask(a.y, b.y));
249}
250template <>
251EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2
252pcmp_lt<double2>(const double2& a, const double2& b) {
253 return make_double2(lt_mask(a.x, b.x), lt_mask(a.y, b.y));
254}
255#endif // defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
256
257template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 plset<float4>(const float& a) {
258 return make_float4(a, a+1, a+2, a+3);
259}
260template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 plset<double2>(const double& a) {
261 return make_double2(a, a+1);
262}
263
264template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 padd<float4>(const float4& a, const float4& b) {
265 return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
266}
267template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 padd<double2>(const double2& a, const double2& b) {
268 return make_double2(a.x+b.x, a.y+b.y);
269}
270
271template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 psub<float4>(const float4& a, const float4& b) {
272 return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
273}
274template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 psub<double2>(const double2& a, const double2& b) {
275 return make_double2(a.x-b.x, a.y-b.y);
276}
277
278template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pnegate(const float4& a) {
279 return make_float4(-a.x, -a.y, -a.z, -a.w);
280}
281template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pnegate(const double2& a) {
282 return make_double2(-a.x, -a.y);
283}
284
285template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pconj(const float4& a) { return a; }
286template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pconj(const double2& a) { return a; }
287
288template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmul<float4>(const float4& a, const float4& b) {
289 return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
290}
291template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmul<double2>(const double2& a, const double2& b) {
292 return make_double2(a.x*b.x, a.y*b.y);
293}
294
295template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pdiv<float4>(const float4& a, const float4& b) {
296 return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
297}
298template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pdiv<double2>(const double2& a, const double2& b) {
299 return make_double2(a.x/b.x, a.y/b.y);
300}
301
302template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmin<float4>(const float4& a, const float4& b) {
303 return make_float4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w));
304}
305template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmin<double2>(const double2& a, const double2& b) {
306 return make_double2(fmin(a.x, b.x), fmin(a.y, b.y));
307}
308
309template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmax<float4>(const float4& a, const float4& b) {
310 return make_float4(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z), fmaxf(a.w, b.w));
311}
312template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmax<double2>(const double2& a, const double2& b) {
313 return make_double2(fmax(a.x, b.x), fmax(a.y, b.y));
314}
315
316template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pload<float4>(const float* from) {
317 return *reinterpret_cast<const float4*>(from);
318}
319
320template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pload<double2>(const double* from) {
321 return *reinterpret_cast<const double2*>(from);
322}
323
324template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploadu<float4>(const float* from) {
325 return make_float4(from[0], from[1], from[2], from[3]);
326}
327template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploadu<double2>(const double* from) {
328 return make_double2(from[0], from[1]);
329}
330
331template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploaddup<float4>(const float* from) {
332 return make_float4(from[0], from[0], from[1], from[1]);
333}
334template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploaddup<double2>(const double* from) {
335 return make_double2(from[0], from[0]);
336}
337
338template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<float>(float* to, const float4& from) {
339 *reinterpret_cast<float4*>(to) = from;
340}
341
342template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<double>(double* to, const double2& from) {
343 *reinterpret_cast<double2*>(to) = from;
344}
345
346template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const float4& from) {
347 to[0] = from.x;
348 to[1] = from.y;
349 to[2] = from.z;
350 to[3] = from.w;
351}
352
353template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const double2& from) {
354 to[0] = from.x;
355 to[1] = from.y;
356}
357
358template<>
359EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Aligned>(const float* from) {
360#if defined(EIGEN_GPU_HAS_LDG)
361 return __ldg((const float4*)from);
362#else
363 return make_float4(from[0], from[1], from[2], from[3]);
364#endif
365}
366template<>
367EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Aligned>(const double* from) {
368#if defined(EIGEN_GPU_HAS_LDG)
369 return __ldg((const double2*)from);
370#else
371 return make_double2(from[0], from[1]);
372#endif
373}
374
375template<>
376EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Unaligned>(const float* from) {
377#if defined(EIGEN_GPU_HAS_LDG)
378 return make_float4(__ldg(from+0), __ldg(from+1), __ldg(from+2), __ldg(from+3));
379#else
380 return make_float4(from[0], from[1], from[2], from[3]);
381#endif
382}
383template<>
384EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Unaligned>(const double* from) {
385#if defined(EIGEN_GPU_HAS_LDG)
386 return make_double2(__ldg(from+0), __ldg(from+1));
387#else
388 return make_double2(from[0], from[1]);
389#endif
390}
391
392template<> EIGEN_DEVICE_FUNC inline float4 pgather<float, float4>(const float* from, Index stride) {
393 return make_float4(from[0*stride], from[1*stride], from[2*stride], from[3*stride]);
394}
395
396template<> EIGEN_DEVICE_FUNC inline double2 pgather<double, double2>(const double* from, Index stride) {
397 return make_double2(from[0*stride], from[1*stride]);
398}
399
400template<> EIGEN_DEVICE_FUNC inline void pscatter<float, float4>(float* to, const float4& from, Index stride) {
401 to[stride*0] = from.x;
402 to[stride*1] = from.y;
403 to[stride*2] = from.z;
404 to[stride*3] = from.w;
405}
406template<> EIGEN_DEVICE_FUNC inline void pscatter<double, double2>(double* to, const double2& from, Index stride) {
407 to[stride*0] = from.x;
408 to[stride*1] = from.y;
409}
410
411template<> EIGEN_DEVICE_FUNC inline float pfirst<float4>(const float4& a) {
412 return a.x;
413}
414template<> EIGEN_DEVICE_FUNC inline double pfirst<double2>(const double2& a) {
415 return a.x;
416}
417
418template<> EIGEN_DEVICE_FUNC inline float predux<float4>(const float4& a) {
419 return a.x + a.y + a.z + a.w;
420}
421template<> EIGEN_DEVICE_FUNC inline double predux<double2>(const double2& a) {
422 return a.x + a.y;
423}
424
425template<> EIGEN_DEVICE_FUNC inline float predux_max<float4>(const float4& a) {
426 return fmaxf(fmaxf(a.x, a.y), fmaxf(a.z, a.w));
427}
428template<> EIGEN_DEVICE_FUNC inline double predux_max<double2>(const double2& a) {
429 return fmax(a.x, a.y);
430}
431
432template<> EIGEN_DEVICE_FUNC inline float predux_min<float4>(const float4& a) {
433 return fminf(fminf(a.x, a.y), fminf(a.z, a.w));
434}
435template<> EIGEN_DEVICE_FUNC inline double predux_min<double2>(const double2& a) {
436 return fmin(a.x, a.y);
437}
438
439template<> EIGEN_DEVICE_FUNC inline float predux_mul<float4>(const float4& a) {
440 return a.x * a.y * a.z * a.w;
441}
442template<> EIGEN_DEVICE_FUNC inline double predux_mul<double2>(const double2& a) {
443 return a.x * a.y;
444}
445
446template<> EIGEN_DEVICE_FUNC inline float4 pabs<float4>(const float4& a) {
447 return make_float4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w));
448}
449template<> EIGEN_DEVICE_FUNC inline double2 pabs<double2>(const double2& a) {
450 return make_double2(fabs(a.x), fabs(a.y));
451}
452
453template<> EIGEN_DEVICE_FUNC inline float4 pfloor<float4>(const float4& a) {
454 return make_float4(floorf(a.x), floorf(a.y), floorf(a.z), floorf(a.w));
455}
456template<> EIGEN_DEVICE_FUNC inline double2 pfloor<double2>(const double2& a) {
457 return make_double2(floor(a.x), floor(a.y));
458}
459
460EIGEN_DEVICE_FUNC inline void
461ptranspose(PacketBlock<float4,4>& kernel) {
462 float tmp = kernel.packet[0].y;
463 kernel.packet[0].y = kernel.packet[1].x;
464 kernel.packet[1].x = tmp;
465
466 tmp = kernel.packet[0].z;
467 kernel.packet[0].z = kernel.packet[2].x;
468 kernel.packet[2].x = tmp;
469
470 tmp = kernel.packet[0].w;
471 kernel.packet[0].w = kernel.packet[3].x;
472 kernel.packet[3].x = tmp;
473
474 tmp = kernel.packet[1].z;
475 kernel.packet[1].z = kernel.packet[2].y;
476 kernel.packet[2].y = tmp;
477
478 tmp = kernel.packet[1].w;
479 kernel.packet[1].w = kernel.packet[3].y;
480 kernel.packet[3].y = tmp;
481
482 tmp = kernel.packet[2].w;
483 kernel.packet[2].w = kernel.packet[3].z;
484 kernel.packet[3].z = tmp;
485}
486
487EIGEN_DEVICE_FUNC inline void
488ptranspose(PacketBlock<double2,2>& kernel) {
489 double tmp = kernel.packet[0].y;
490 kernel.packet[0].y = kernel.packet[1].x;
491 kernel.packet[1].x = tmp;
492}
493
494#endif // defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
495
496// Half-packet functions are not available on the host for CUDA 9.0-9.2, only
497// on device. There is no benefit to using them on the host anyways, since they are
498// emulated.
499#if (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
500
501typedef ulonglong2 Packet4h2;
502template<> 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; };
503template<> struct is_arithmetic<Packet4h2> { enum { value = true }; };
504
505template<> 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; };
506template<> struct is_arithmetic<half2> { enum { value = true }; };
507
508template<> struct packet_traits<Eigen::half> : default_packet_traits
509{
510 typedef Packet4h2 type;
511 typedef Packet4h2 half;
512 enum {
513 Vectorizable = 1,
514 AlignedOnScalar = 1,
515 size=8,
516 HasHalfPacket = 0,
517 HasAdd = 1,
518 HasSub = 1,
519 HasMul = 1,
520 HasDiv = 1,
521 HasSqrt = 1,
522 HasRsqrt = 1,
523 HasExp = 1,
524 HasExpm1 = 1,
525 HasLog = 1,
526 HasLog1p = 1
527 };
528};
529
530template<>
531EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
532 return __half2half2(from);
533}
534
535template <>
536EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
537pset1<Packet4h2>(const Eigen::half& from) {
538 Packet4h2 r;
539 half2* p_alias = reinterpret_cast<half2*>(&r);
540 p_alias[0] = pset1<half2>(from);
541 p_alias[1] = pset1<half2>(from);
542 p_alias[2] = pset1<half2>(from);
543 p_alias[3] = pset1<half2>(from);
544 return r;
545}
546
547namespace {
548
549EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const Eigen::half* from) {
550 return *reinterpret_cast<const half2*>(from);
551}
552
553EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu(const Eigen::half* from) {
554 return __halves2half2(from[0], from[1]);
555}
556
557EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploaddup(const Eigen::half* from) {
558 return __halves2half2(from[0], from[0]);
559}
560
561EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(Eigen::half* to,
562 const half2& from) {
563 *reinterpret_cast<half2*>(to) = from;
564}
565
566EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu(Eigen::half* to,
567 const half2& from) {
568 to[0] = __low2half(from);
569 to[1] = __high2half(from);
570}
571
572
573EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_aligned(
574 const Eigen::half* from) {
575#if defined(EIGEN_GPU_HAS_LDG)
576 // Input is guaranteed to be properly aligned.
577 return __ldg(reinterpret_cast<const half2*>(from));
578#else
579 return __halves2half2(*(from+0), *(from+1));
580#endif
581}
582
583EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_unaligned(
584 const Eigen::half* from) {
585#if defined(EIGEN_GPU_HAS_LDG)
586 return __halves2half2(__ldg(from+0), __ldg(from+1));
587#else
588 return __halves2half2(*(from+0), *(from+1));
589#endif
590}
591
592EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pgather(const Eigen::half* from,
593 Index stride) {
594 return __halves2half2(from[0*stride], from[1*stride]);
595}
596
597EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter(
598 Eigen::half* to, const half2& from, Index stride) {
599 to[stride*0] = __low2half(from);
600 to[stride*1] = __high2half(from);
601}
602
603EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& a) {
604 return __low2half(a);
605}
606
607EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pabs(const half2& a) {
608 half a1 = __low2half(a);
609 half a2 = __high2half(a);
610 half result1 = half_impl::raw_uint16_to_half(a1.x & 0x7FFF);
611 half result2 = half_impl::raw_uint16_to_half(a2.x & 0x7FFF);
612 return __halves2half2(result1, result2);
613}
614
615EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ptrue(const half2& /*a*/) {
616 half true_half = half_impl::raw_uint16_to_half(0xffffu);
617 return pset1<half2>(true_half);
618}
619
620EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pzero(const half2& /*a*/) {
621 half false_half = half_impl::raw_uint16_to_half(0x0000u);
622 return pset1<half2>(false_half);
623}
624
625EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
626ptranspose(PacketBlock<half2,2>& kernel) {
627 __half a1 = __low2half(kernel.packet[0]);
628 __half a2 = __high2half(kernel.packet[0]);
629 __half b1 = __low2half(kernel.packet[1]);
630 __half b2 = __high2half(kernel.packet[1]);
631 kernel.packet[0] = __halves2half2(a1, b1);
632 kernel.packet[1] = __halves2half2(a2, b2);
633}
634
635EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const Eigen::half& a) {
636#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
637 return __halves2half2(a, __hadd(a, __float2half(1.0f)));
638#else
639 float f = __half2float(a) + 1.0f;
640 return __halves2half2(a, __float2half(f));
641#endif
642}
643
644EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pselect(const half2& mask,
645 const half2& a,
646 const half2& b) {
647 half mask_low = __low2half(mask);
648 half mask_high = __high2half(mask);
649 half result_low = mask_low == half(0) ? __low2half(b) : __low2half(a);
650 half result_high = mask_high == half(0) ? __high2half(b) : __high2half(a);
651 return __halves2half2(result_low, result_high);
652}
653
654EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_eq(const half2& a,
655 const half2& b) {
656 half true_half = half_impl::raw_uint16_to_half(0xffffu);
657 half false_half = half_impl::raw_uint16_to_half(0x0000u);
658 half a1 = __low2half(a);
659 half a2 = __high2half(a);
660 half b1 = __low2half(b);
661 half b2 = __high2half(b);
662 half eq1 = __half2float(a1) == __half2float(b1) ? true_half : false_half;
663 half eq2 = __half2float(a2) == __half2float(b2) ? true_half : false_half;
664 return __halves2half2(eq1, eq2);
665}
666
667EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_lt(const half2& a,
668 const half2& b) {
669 half true_half = half_impl::raw_uint16_to_half(0xffffu);
670 half false_half = half_impl::raw_uint16_to_half(0x0000u);
671 half a1 = __low2half(a);
672 half a2 = __high2half(a);
673 half b1 = __low2half(b);
674 half b2 = __high2half(b);
675 half eq1 = __half2float(a1) < __half2float(b1) ? true_half : false_half;
676 half eq2 = __half2float(a2) < __half2float(b2) ? true_half : false_half;
677 return __halves2half2(eq1, eq2);
678}
679
680EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pand(const half2& a,
681 const half2& b) {
682 half a1 = __low2half(a);
683 half a2 = __high2half(a);
684 half b1 = __low2half(b);
685 half b2 = __high2half(b);
686 half result1 = half_impl::raw_uint16_to_half(a1.x & b1.x);
687 half result2 = half_impl::raw_uint16_to_half(a2.x & b2.x);
688 return __halves2half2(result1, result2);
689}
690
691EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 por(const half2& a,
692 const half2& b) {
693 half a1 = __low2half(a);
694 half a2 = __high2half(a);
695 half b1 = __low2half(b);
696 half b2 = __high2half(b);
697 half result1 = half_impl::raw_uint16_to_half(a1.x | b1.x);
698 half result2 = half_impl::raw_uint16_to_half(a2.x | b2.x);
699 return __halves2half2(result1, result2);
700}
701
702EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pxor(const half2& a,
703 const half2& b) {
704 half a1 = __low2half(a);
705 half a2 = __high2half(a);
706 half b1 = __low2half(b);
707 half b2 = __high2half(b);
708 half result1 = half_impl::raw_uint16_to_half(a1.x ^ b1.x);
709 half result2 = half_impl::raw_uint16_to_half(a2.x ^ b2.x);
710 return __halves2half2(result1, result2);
711}
712
713EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pandnot(const half2& a,
714 const half2& b) {
715 half a1 = __low2half(a);
716 half a2 = __high2half(a);
717 half b1 = __low2half(b);
718 half b2 = __high2half(b);
719 half result1 = half_impl::raw_uint16_to_half(a1.x & ~b1.x);
720 half result2 = half_impl::raw_uint16_to_half(a2.x & ~b2.x);
721 return __halves2half2(result1, result2);
722}
723
724EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd(const half2& a,
725 const half2& b) {
726#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
727 return __hadd2(a, b);
728#else
729 float a1 = __low2float(a);
730 float a2 = __high2float(a);
731 float b1 = __low2float(b);
732 float b2 = __high2float(b);
733 float r1 = a1 + b1;
734 float r2 = a2 + b2;
735 return __floats2half2_rn(r1, r2);
736#endif
737}
738
739EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub(const half2& a,
740 const half2& b) {
741#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
742 return __hsub2(a, b);
743#else
744 float a1 = __low2float(a);
745 float a2 = __high2float(a);
746 float b1 = __low2float(b);
747 float b2 = __high2float(b);
748 float r1 = a1 - b1;
749 float r2 = a2 - b2;
750 return __floats2half2_rn(r1, r2);
751#endif
752}
753
754EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
755#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
756 return __hneg2(a);
757#else
758 float a1 = __low2float(a);
759 float a2 = __high2float(a);
760 return __floats2half2_rn(-a1, -a2);
761#endif
762}
763
764EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; }
765
766EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul(const half2& a,
767 const half2& b) {
768#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
769 return __hmul2(a, b);
770#else
771 float a1 = __low2float(a);
772 float a2 = __high2float(a);
773 float b1 = __low2float(b);
774 float b2 = __high2float(b);
775 float r1 = a1 * b1;
776 float r2 = a2 * b2;
777 return __floats2half2_rn(r1, r2);
778#endif
779}
780
781EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd(const half2& a,
782 const half2& b,
783 const half2& c) {
784#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
785 return __hfma2(a, b, c);
786#else
787 float a1 = __low2float(a);
788 float a2 = __high2float(a);
789 float b1 = __low2float(b);
790 float b2 = __high2float(b);
791 float c1 = __low2float(c);
792 float c2 = __high2float(c);
793 float r1 = a1 * b1 + c1;
794 float r2 = a2 * b2 + c2;
795 return __floats2half2_rn(r1, r2);
796#endif
797}
798
799EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv(const half2& a,
800 const half2& b) {
801#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
802 return __h2div(a, b);
803#else
804 float a1 = __low2float(a);
805 float a2 = __high2float(a);
806 float b1 = __low2float(b);
807 float b2 = __high2float(b);
808 float r1 = a1 / b1;
809 float r2 = a2 / b2;
810 return __floats2half2_rn(r1, r2);
811#endif
812}
813
814EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin(const half2& a,
815 const half2& b) {
816 float a1 = __low2float(a);
817 float a2 = __high2float(a);
818 float b1 = __low2float(b);
819 float b2 = __high2float(b);
820 __half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
821 __half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
822 return __halves2half2(r1, r2);
823}
824
825EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a,
826 const half2& b) {
827 float a1 = __low2float(a);
828 float a2 = __high2float(a);
829 float b1 = __low2float(b);
830 float b2 = __high2float(b);
831 __half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
832 __half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
833 return __halves2half2(r1, r2);
834}
835
836EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux(const half2& a) {
837#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
838 return __hadd(__low2half(a), __high2half(a));
839#else
840 float a1 = __low2float(a);
841 float a2 = __high2float(a);
842 return Eigen::half(__float2half(a1 + a2));
843#endif
844}
845
846EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max(const half2& a) {
847#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
848 __half first = __low2half(a);
849 __half second = __high2half(a);
850 return __hgt(first, second) ? first : second;
851#else
852 float a1 = __low2float(a);
853 float a2 = __high2float(a);
854 return a1 > a2 ? __low2half(a) : __high2half(a);
855#endif
856}
857
858EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min(const half2& a) {
859#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
860 __half first = __low2half(a);
861 __half second = __high2half(a);
862 return __hlt(first, second) ? first : second;
863#else
864 float a1 = __low2float(a);
865 float a2 = __high2float(a);
866 return a1 < a2 ? __low2half(a) : __high2half(a);
867#endif
868}
869
870EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul(const half2& a) {
871#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
872 return __hmul(__low2half(a), __high2half(a));
873#else
874 float a1 = __low2float(a);
875 float a2 = __high2float(a);
876 return Eigen::half(__float2half(a1 * a2));
877#endif
878}
879
880EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog1p(const half2& a) {
881 float a1 = __low2float(a);
882 float a2 = __high2float(a);
883 float r1 = log1pf(a1);
884 float r2 = log1pf(a2);
885 return __floats2half2_rn(r1, r2);
886}
887
888EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexpm1(const half2& a) {
889 float a1 = __low2float(a);
890 float a2 = __high2float(a);
891 float r1 = expm1f(a1);
892 float r2 = expm1f(a2);
893 return __floats2half2_rn(r1, r2);
894}
895
896#if (EIGEN_CUDA_SDK_VER >= 80000 && defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)) || \
897 defined(EIGEN_HIP_DEVICE_COMPILE)
898
899EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
900half2 plog(const half2& a) {
901 return h2log(a);
902}
903
904 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
905half2 pexp(const half2& a) {
906 return h2exp(a);
907}
908
909 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
910half2 psqrt(const half2& a) {
911 return h2sqrt(a);
912}
913
914 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
915half2 prsqrt(const half2& a) {
916 return h2rsqrt(a);
917}
918
919#else
920
921EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog(const half2& a) {
922 float a1 = __low2float(a);
923 float a2 = __high2float(a);
924 float r1 = logf(a1);
925 float r2 = logf(a2);
926 return __floats2half2_rn(r1, r2);
927}
928
929EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp(const half2& a) {
930 float a1 = __low2float(a);
931 float a2 = __high2float(a);
932 float r1 = expf(a1);
933 float r2 = expf(a2);
934 return __floats2half2_rn(r1, r2);
935}
936
937EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt(const half2& a) {
938 float a1 = __low2float(a);
939 float a2 = __high2float(a);
940 float r1 = sqrtf(a1);
941 float r2 = sqrtf(a2);
942 return __floats2half2_rn(r1, r2);
943}
944
945EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt(const half2& a) {
946 float a1 = __low2float(a);
947 float a2 = __high2float(a);
948 float r1 = rsqrtf(a1);
949 float r2 = rsqrtf(a2);
950 return __floats2half2_rn(r1, r2);
951}
952#endif
953} // namespace
954
955template <>
956EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
957pload<Packet4h2>(const Eigen::half* from) {
958 return *reinterpret_cast<const Packet4h2*>(from);
959}
960
961// unaligned load;
962template <>
963EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
964ploadu<Packet4h2>(const Eigen::half* from) {
965 Packet4h2 r;
966 half2* p_alias = reinterpret_cast<half2*>(&r);
967 p_alias[0] = ploadu(from + 0);
968 p_alias[1] = ploadu(from + 2);
969 p_alias[2] = ploadu(from + 4);
970 p_alias[3] = ploadu(from + 6);
971 return r;
972}
973
974template <>
975EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
976ploaddup<Packet4h2>(const Eigen::half* from) {
977 Packet4h2 r;
978 half2* p_alias = reinterpret_cast<half2*>(&r);
979 p_alias[0] = ploaddup(from + 0);
980 p_alias[1] = ploaddup(from + 1);
981 p_alias[2] = ploaddup(from + 2);
982 p_alias[3] = ploaddup(from + 3);
983 return r;
984}
985
986template <>
987EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<Eigen::half>(
988 Eigen::half* to, const Packet4h2& from) {
989 *reinterpret_cast<Packet4h2*>(to) = from;
990}
991
992template <>
993EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(
994 Eigen::half* to, const Packet4h2& from) {
995 const half2* from_alias = reinterpret_cast<const half2*>(&from);
996 pstoreu(to + 0,from_alias[0]);
997 pstoreu(to + 2,from_alias[1]);
998 pstoreu(to + 4,from_alias[2]);
999 pstoreu(to + 6,from_alias[3]);
1000}
1001
1002template <>
1003EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2
1004ploadt_ro<Packet4h2, Aligned>(const Eigen::half* from) {
1005#if defined(EIGEN_GPU_HAS_LDG)
1006 Packet4h2 r;
1007 r = __ldg(reinterpret_cast<const Packet4h2*>(from));
1008 return r;
1009#else
1010 Packet4h2 r;
1011 half2* r_alias = reinterpret_cast<half2*>(&r);
1012 r_alias[0] = ploadt_ro_aligned(from + 0);
1013 r_alias[1] = ploadt_ro_aligned(from + 2);
1014 r_alias[2] = ploadt_ro_aligned(from + 4);
1015 r_alias[3] = ploadt_ro_aligned(from + 6);
1016 return r;
1017#endif
1018}
1019
1020template <>
1021EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2
1022ploadt_ro<Packet4h2, Unaligned>(const Eigen::half* from) {
1023 Packet4h2 r;
1024 half2* r_alias = reinterpret_cast<half2*>(&r);
1025 r_alias[0] = ploadt_ro_unaligned(from + 0);
1026 r_alias[1] = ploadt_ro_unaligned(from + 2);
1027 r_alias[2] = ploadt_ro_unaligned(from + 4);
1028 r_alias[3] = ploadt_ro_unaligned(from + 6);
1029 return r;
1030}
1031
1032template <>
1033EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1034pgather<Eigen::half, Packet4h2>(const Eigen::half* from, Index stride) {
1035 Packet4h2 r;
1036 half2* p_alias = reinterpret_cast<half2*>(&r);
1037 p_alias[0] = __halves2half2(from[0 * stride], from[1 * stride]);
1038 p_alias[1] = __halves2half2(from[2 * stride], from[3 * stride]);
1039 p_alias[2] = __halves2half2(from[4 * stride], from[5 * stride]);
1040 p_alias[3] = __halves2half2(from[6 * stride], from[7 * stride]);
1041 return r;
1042}
1043
1044template <>
1045EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet4h2>(
1046 Eigen::half* to, const Packet4h2& from, Index stride) {
1047 const half2* from_alias = reinterpret_cast<const half2*>(&from);
1048 pscatter(to + stride * 0, from_alias[0], stride);
1049 pscatter(to + stride * 2, from_alias[1], stride);
1050 pscatter(to + stride * 4, from_alias[2], stride);
1051 pscatter(to + stride * 6, from_alias[3], stride);
1052}
1053
1054template <>
1055EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst<Packet4h2>(
1056 const Packet4h2& a) {
1057 return pfirst(*(reinterpret_cast<const half2*>(&a)));
1058}
1059
1060template <>
1061EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pabs<Packet4h2>(
1062 const Packet4h2& a) {
1063 Packet4h2 r;
1064 half2* p_alias = reinterpret_cast<half2*>(&r);
1065 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1066 p_alias[0] = pabs(a_alias[0]);
1067 p_alias[1] = pabs(a_alias[1]);
1068 p_alias[2] = pabs(a_alias[2]);
1069 p_alias[3] = pabs(a_alias[3]);
1070 return r;
1071}
1072
1073template <>
1074EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 ptrue<Packet4h2>(
1075 const Packet4h2& /*a*/) {
1076 half true_half = half_impl::raw_uint16_to_half(0xffffu);
1077 return pset1<Packet4h2>(true_half);
1078}
1079
1080template <>
1081EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pzero<Packet4h2>(const Packet4h2& /*a*/) {
1082 half false_half = half_impl::raw_uint16_to_half(0x0000u);
1083 return pset1<Packet4h2>(false_half);
1084}
1085
1086EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_double(
1087 double* d_row0, double* d_row1, double* d_row2, double* d_row3,
1088 double* d_row4, double* d_row5, double* d_row6, double* d_row7) {
1089 double d_tmp;
1090 d_tmp = d_row0[1];
1091 d_row0[1] = d_row4[0];
1092 d_row4[0] = d_tmp;
1093
1094 d_tmp = d_row1[1];
1095 d_row1[1] = d_row5[0];
1096 d_row5[0] = d_tmp;
1097
1098 d_tmp = d_row2[1];
1099 d_row2[1] = d_row6[0];
1100 d_row6[0] = d_tmp;
1101
1102 d_tmp = d_row3[1];
1103 d_row3[1] = d_row7[0];
1104 d_row7[0] = d_tmp;
1105}
1106
1107EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_half2(
1108 half2* f_row0, half2* f_row1, half2* f_row2, half2* f_row3) {
1109 half2 f_tmp;
1110 f_tmp = f_row0[1];
1111 f_row0[1] = f_row2[0];
1112 f_row2[0] = f_tmp;
1113
1114 f_tmp = f_row1[1];
1115 f_row1[1] = f_row3[0];
1116 f_row3[0] = f_tmp;
1117}
1118
1119EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
1120ptranspose_half(half2& f0, half2& f1) {
1121 __half a1 = __low2half(f0);
1122 __half a2 = __high2half(f0);
1123 __half b1 = __low2half(f1);
1124 __half b2 = __high2half(f1);
1125 f0 = __halves2half2(a1, b1);
1126 f1 = __halves2half2(a2, b2);
1127}
1128
1129EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
1130ptranspose(PacketBlock<Packet4h2,8>& kernel) {
1131 double* d_row0 = reinterpret_cast<double*>(&kernel.packet[0]);
1132 double* d_row1 = reinterpret_cast<double*>(&kernel.packet[1]);
1133 double* d_row2 = reinterpret_cast<double*>(&kernel.packet[2]);
1134 double* d_row3 = reinterpret_cast<double*>(&kernel.packet[3]);
1135 double* d_row4 = reinterpret_cast<double*>(&kernel.packet[4]);
1136 double* d_row5 = reinterpret_cast<double*>(&kernel.packet[5]);
1137 double* d_row6 = reinterpret_cast<double*>(&kernel.packet[6]);
1138 double* d_row7 = reinterpret_cast<double*>(&kernel.packet[7]);
1139 ptranspose_double(d_row0, d_row1, d_row2, d_row3,
1140 d_row4, d_row5, d_row6, d_row7);
1141
1142
1143 half2* f_row0 = reinterpret_cast<half2*>(d_row0);
1144 half2* f_row1 = reinterpret_cast<half2*>(d_row1);
1145 half2* f_row2 = reinterpret_cast<half2*>(d_row2);
1146 half2* f_row3 = reinterpret_cast<half2*>(d_row3);
1147 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1148 ptranspose_half(f_row0[0], f_row1[0]);
1149 ptranspose_half(f_row0[1], f_row1[1]);
1150 ptranspose_half(f_row2[0], f_row3[0]);
1151 ptranspose_half(f_row2[1], f_row3[1]);
1152
1153 f_row0 = reinterpret_cast<half2*>(d_row0 + 1);
1154 f_row1 = reinterpret_cast<half2*>(d_row1 + 1);
1155 f_row2 = reinterpret_cast<half2*>(d_row2 + 1);
1156 f_row3 = reinterpret_cast<half2*>(d_row3 + 1);
1157 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1158 ptranspose_half(f_row0[0], f_row1[0]);
1159 ptranspose_half(f_row0[1], f_row1[1]);
1160 ptranspose_half(f_row2[0], f_row3[0]);
1161 ptranspose_half(f_row2[1], f_row3[1]);
1162
1163 f_row0 = reinterpret_cast<half2*>(d_row4);
1164 f_row1 = reinterpret_cast<half2*>(d_row5);
1165 f_row2 = reinterpret_cast<half2*>(d_row6);
1166 f_row3 = reinterpret_cast<half2*>(d_row7);
1167 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1168 ptranspose_half(f_row0[0], f_row1[0]);
1169 ptranspose_half(f_row0[1], f_row1[1]);
1170 ptranspose_half(f_row2[0], f_row3[0]);
1171 ptranspose_half(f_row2[1], f_row3[1]);
1172
1173 f_row0 = reinterpret_cast<half2*>(d_row4 + 1);
1174 f_row1 = reinterpret_cast<half2*>(d_row5 + 1);
1175 f_row2 = reinterpret_cast<half2*>(d_row6 + 1);
1176 f_row3 = reinterpret_cast<half2*>(d_row7 + 1);
1177 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1178 ptranspose_half(f_row0[0], f_row1[0]);
1179 ptranspose_half(f_row0[1], f_row1[1]);
1180 ptranspose_half(f_row2[0], f_row3[0]);
1181 ptranspose_half(f_row2[1], f_row3[1]);
1182
1183}
1184
1185template <>
1186EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1187plset<Packet4h2>(const Eigen::half& a) {
1188#if defined(EIGEN_HIP_DEVICE_COMPILE)
1189
1190 Packet4h2 r;
1191 half2* p_alias = reinterpret_cast<half2*>(&r);
1192 p_alias[0] = __halves2half2(a, __hadd(a, __float2half(1.0f)));
1193 p_alias[1] = __halves2half2(__hadd(a, __float2half(2.0f)),
1194 __hadd(a, __float2half(3.0f)));
1195 p_alias[2] = __halves2half2(__hadd(a, __float2half(4.0f)),
1196 __hadd(a, __float2half(5.0f)));
1197 p_alias[3] = __halves2half2(__hadd(a, __float2half(6.0f)),
1198 __hadd(a, __float2half(7.0f)));
1199 return r;
1200#elif defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1201 Packet4h2 r;
1202 half2* r_alias = reinterpret_cast<half2*>(&r);
1203
1204 half2 b = pset1<half2>(a);
1205 half2 c;
1206 half2 half_offset0 = __halves2half2(__float2half(0.0f),__float2half(2.0f));
1207 half2 half_offset1 = __halves2half2(__float2half(4.0f),__float2half(6.0f));
1208
1209 c = __hadd2(b, half_offset0);
1210 r_alias[0] = plset(__low2half(c));
1211 r_alias[1] = plset(__high2half(c));
1212
1213 c = __hadd2(b, half_offset1);
1214 r_alias[2] = plset(__low2half(c));
1215 r_alias[3] = plset(__high2half(c));
1216
1217 return r;
1218
1219#else
1220 float f = __half2float(a);
1221 Packet4h2 r;
1222 half2* p_alias = reinterpret_cast<half2*>(&r);
1223 p_alias[0] = __halves2half2(a, __float2half(f + 1.0f));
1224 p_alias[1] = __halves2half2(__float2half(f + 2.0f), __float2half(f + 3.0f));
1225 p_alias[2] = __halves2half2(__float2half(f + 4.0f), __float2half(f + 5.0f));
1226 p_alias[3] = __halves2half2(__float2half(f + 6.0f), __float2half(f + 7.0f));
1227 return r;
1228#endif
1229}
1230
1231template <>
1232EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1233pselect<Packet4h2>(const Packet4h2& mask, const Packet4h2& a,
1234 const Packet4h2& b) {
1235 Packet4h2 r;
1236 half2* r_alias = reinterpret_cast<half2*>(&r);
1237 const half2* mask_alias = reinterpret_cast<const half2*>(&mask);
1238 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1239 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1240 r_alias[0] = pselect(mask_alias[0], a_alias[0], b_alias[0]);
1241 r_alias[1] = pselect(mask_alias[1], a_alias[1], b_alias[1]);
1242 r_alias[2] = pselect(mask_alias[2], a_alias[2], b_alias[2]);
1243 r_alias[3] = pselect(mask_alias[3], a_alias[3], b_alias[3]);
1244 return r;
1245}
1246
1247template <>
1248EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1249pcmp_eq<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
1250 Packet4h2 r;
1251 half2* r_alias = reinterpret_cast<half2*>(&r);
1252 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1253 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1254 r_alias[0] = pcmp_eq(a_alias[0], b_alias[0]);
1255 r_alias[1] = pcmp_eq(a_alias[1], b_alias[1]);
1256 r_alias[2] = pcmp_eq(a_alias[2], b_alias[2]);
1257 r_alias[3] = pcmp_eq(a_alias[3], b_alias[3]);
1258 return r;
1259}
1260
1261template <>
1262EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pand<Packet4h2>(
1263 const Packet4h2& a, const Packet4h2& b) {
1264 Packet4h2 r;
1265 half2* r_alias = reinterpret_cast<half2*>(&r);
1266 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1267 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1268 r_alias[0] = pand(a_alias[0], b_alias[0]);
1269 r_alias[1] = pand(a_alias[1], b_alias[1]);
1270 r_alias[2] = pand(a_alias[2], b_alias[2]);
1271 r_alias[3] = pand(a_alias[3], b_alias[3]);
1272 return r;
1273}
1274
1275template <>
1276EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 por<Packet4h2>(
1277 const Packet4h2& a, const Packet4h2& b) {
1278 Packet4h2 r;
1279 half2* r_alias = reinterpret_cast<half2*>(&r);
1280 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1281 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1282 r_alias[0] = por(a_alias[0], b_alias[0]);
1283 r_alias[1] = por(a_alias[1], b_alias[1]);
1284 r_alias[2] = por(a_alias[2], b_alias[2]);
1285 r_alias[3] = por(a_alias[3], b_alias[3]);
1286 return r;
1287}
1288
1289template <>
1290EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pxor<Packet4h2>(
1291 const Packet4h2& a, const Packet4h2& b) {
1292 Packet4h2 r;
1293 half2* r_alias = reinterpret_cast<half2*>(&r);
1294 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1295 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1296 r_alias[0] = pxor(a_alias[0], b_alias[0]);
1297 r_alias[1] = pxor(a_alias[1], b_alias[1]);
1298 r_alias[2] = pxor(a_alias[2], b_alias[2]);
1299 r_alias[3] = pxor(a_alias[3], b_alias[3]);
1300 return r;
1301}
1302
1303template <>
1304EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1305pandnot<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
1306 Packet4h2 r;
1307 half2* r_alias = reinterpret_cast<half2*>(&r);
1308 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1309 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1310 r_alias[0] = pandnot(a_alias[0], b_alias[0]);
1311 r_alias[1] = pandnot(a_alias[1], b_alias[1]);
1312 r_alias[2] = pandnot(a_alias[2], b_alias[2]);
1313 r_alias[3] = pandnot(a_alias[3], b_alias[3]);
1314 return r;
1315}
1316
1317template <>
1318EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 padd<Packet4h2>(
1319 const Packet4h2& a, const Packet4h2& b) {
1320 Packet4h2 r;
1321 half2* r_alias = reinterpret_cast<half2*>(&r);
1322 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1323 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1324 r_alias[0] = padd(a_alias[0], b_alias[0]);
1325 r_alias[1] = padd(a_alias[1], b_alias[1]);
1326 r_alias[2] = padd(a_alias[2], b_alias[2]);
1327 r_alias[3] = padd(a_alias[3], b_alias[3]);
1328 return r;
1329}
1330
1331template <>
1332EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psub<Packet4h2>(
1333 const Packet4h2& a, const Packet4h2& b) {
1334 Packet4h2 r;
1335 half2* r_alias = reinterpret_cast<half2*>(&r);
1336 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1337 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1338 r_alias[0] = psub(a_alias[0], b_alias[0]);
1339 r_alias[1] = psub(a_alias[1], b_alias[1]);
1340 r_alias[2] = psub(a_alias[2], b_alias[2]);
1341 r_alias[3] = psub(a_alias[3], b_alias[3]);
1342 return r;
1343}
1344
1345template <>
1346EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pnegate(const Packet4h2& a) {
1347 Packet4h2 r;
1348 half2* r_alias = reinterpret_cast<half2*>(&r);
1349 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1350 r_alias[0] = pnegate(a_alias[0]);
1351 r_alias[1] = pnegate(a_alias[1]);
1352 r_alias[2] = pnegate(a_alias[2]);
1353 r_alias[3] = pnegate(a_alias[3]);
1354 return r;
1355}
1356
1357template <>
1358EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pconj(const Packet4h2& a) {
1359 return a;
1360}
1361
1362template <>
1363EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmul<Packet4h2>(
1364 const Packet4h2& a, const Packet4h2& b) {
1365 Packet4h2 r;
1366 half2* r_alias = reinterpret_cast<half2*>(&r);
1367 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1368 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1369 r_alias[0] = pmul(a_alias[0], b_alias[0]);
1370 r_alias[1] = pmul(a_alias[1], b_alias[1]);
1371 r_alias[2] = pmul(a_alias[2], b_alias[2]);
1372 r_alias[3] = pmul(a_alias[3], b_alias[3]);
1373 return r;
1374}
1375
1376template <>
1377EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmadd<Packet4h2>(
1378 const Packet4h2& a, const Packet4h2& b, const Packet4h2& c) {
1379 Packet4h2 r;
1380 half2* r_alias = reinterpret_cast<half2*>(&r);
1381 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1382 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1383 const half2* c_alias = reinterpret_cast<const half2*>(&c);
1384 r_alias[0] = pmadd(a_alias[0], b_alias[0], c_alias[0]);
1385 r_alias[1] = pmadd(a_alias[1], b_alias[1], c_alias[1]);
1386 r_alias[2] = pmadd(a_alias[2], b_alias[2], c_alias[2]);
1387 r_alias[3] = pmadd(a_alias[3], b_alias[3], c_alias[3]);
1388 return r;
1389}
1390
1391template <>
1392EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pdiv<Packet4h2>(
1393 const Packet4h2& a, const Packet4h2& b) {
1394 Packet4h2 r;
1395 half2* r_alias = reinterpret_cast<half2*>(&r);
1396 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1397 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1398 r_alias[0] = pdiv(a_alias[0], b_alias[0]);
1399 r_alias[1] = pdiv(a_alias[1], b_alias[1]);
1400 r_alias[2] = pdiv(a_alias[2], b_alias[2]);
1401 r_alias[3] = pdiv(a_alias[3], b_alias[3]);
1402 return r;
1403}
1404
1405template <>
1406EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmin<Packet4h2>(
1407 const Packet4h2& a, const Packet4h2& b) {
1408 Packet4h2 r;
1409 half2* r_alias = reinterpret_cast<half2*>(&r);
1410 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1411 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1412 r_alias[0] = pmin(a_alias[0], b_alias[0]);
1413 r_alias[1] = pmin(a_alias[1], b_alias[1]);
1414 r_alias[2] = pmin(a_alias[2], b_alias[2]);
1415 r_alias[3] = pmin(a_alias[3], b_alias[3]);
1416 return r;
1417}
1418
1419template <>
1420EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmax<Packet4h2>(
1421 const Packet4h2& a, const Packet4h2& b) {
1422 Packet4h2 r;
1423 half2* r_alias = reinterpret_cast<half2*>(&r);
1424 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1425 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1426 r_alias[0] = pmax(a_alias[0], b_alias[0]);
1427 r_alias[1] = pmax(a_alias[1], b_alias[1]);
1428 r_alias[2] = pmax(a_alias[2], b_alias[2]);
1429 r_alias[3] = pmax(a_alias[3], b_alias[3]);
1430 return r;
1431}
1432
1433template <>
1434EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<Packet4h2>(
1435 const Packet4h2& a) {
1436 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1437
1438 return predux(a_alias[0]) + predux(a_alias[1]) +
1439 predux(a_alias[2]) + predux(a_alias[3]);
1440}
1441
1442template <>
1443EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<Packet4h2>(
1444 const Packet4h2& a) {
1445 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1446 half2 m0 = __halves2half2(predux_max(a_alias[0]),
1447 predux_max(a_alias[1]));
1448 half2 m1 = __halves2half2(predux_max(a_alias[2]),
1449 predux_max(a_alias[3]));
1450 __half first = predux_max(m0);
1451 __half second = predux_max(m1);
1452#if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1453 return (__hgt(first, second) ? first : second);
1454#else
1455 float ffirst = __half2float(first);
1456 float fsecond = __half2float(second);
1457 return (ffirst > fsecond)? first: second;
1458#endif
1459}
1460
1461template <>
1462EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<Packet4h2>(
1463 const Packet4h2& a) {
1464 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1465 half2 m0 = __halves2half2(predux_min(a_alias[0]),
1466 predux_min(a_alias[1]));
1467 half2 m1 = __halves2half2(predux_min(a_alias[2]),
1468 predux_min(a_alias[3]));
1469 __half first = predux_min(m0);
1470 __half second = predux_min(m1);
1471#if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
1472 return (__hlt(first, second) ? first : second);
1473#else
1474 float ffirst = __half2float(first);
1475 float fsecond = __half2float(second);
1476 return (ffirst < fsecond)? first: second;
1477#endif
1478}
1479
1480// likely overflow/underflow
1481template <>
1482EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet4h2>(
1483 const Packet4h2& a) {
1484 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1485 return predux_mul(pmul(pmul(a_alias[0], a_alias[1]),
1486 pmul(a_alias[2], a_alias[3])));
1487}
1488
1489template <>
1490EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1491plog1p<Packet4h2>(const Packet4h2& a) {
1492 Packet4h2 r;
1493 half2* r_alias = reinterpret_cast<half2*>(&r);
1494 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1495 r_alias[0] = plog1p(a_alias[0]);
1496 r_alias[1] = plog1p(a_alias[1]);
1497 r_alias[2] = plog1p(a_alias[2]);
1498 r_alias[3] = plog1p(a_alias[3]);
1499 return r;
1500}
1501
1502template <>
1503EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1504pexpm1<Packet4h2>(const Packet4h2& a) {
1505 Packet4h2 r;
1506 half2* r_alias = reinterpret_cast<half2*>(&r);
1507 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1508 r_alias[0] = pexpm1(a_alias[0]);
1509 r_alias[1] = pexpm1(a_alias[1]);
1510 r_alias[2] = pexpm1(a_alias[2]);
1511 r_alias[3] = pexpm1(a_alias[3]);
1512 return r;
1513}
1514
1515template <>
1516EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 plog<Packet4h2>(const Packet4h2& a) {
1517 Packet4h2 r;
1518 half2* r_alias = reinterpret_cast<half2*>(&r);
1519 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1520 r_alias[0] = plog(a_alias[0]);
1521 r_alias[1] = plog(a_alias[1]);
1522 r_alias[2] = plog(a_alias[2]);
1523 r_alias[3] = plog(a_alias[3]);
1524 return r;
1525}
1526
1527template <>
1528EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pexp<Packet4h2>(const Packet4h2& a) {
1529 Packet4h2 r;
1530 half2* r_alias = reinterpret_cast<half2*>(&r);
1531 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1532 r_alias[0] = pexp(a_alias[0]);
1533 r_alias[1] = pexp(a_alias[1]);
1534 r_alias[2] = pexp(a_alias[2]);
1535 r_alias[3] = pexp(a_alias[3]);
1536 return r;
1537}
1538
1539template <>
1540EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psqrt<Packet4h2>(const Packet4h2& a) {
1541 Packet4h2 r;
1542 half2* r_alias = reinterpret_cast<half2*>(&r);
1543 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1544 r_alias[0] = psqrt(a_alias[0]);
1545 r_alias[1] = psqrt(a_alias[1]);
1546 r_alias[2] = psqrt(a_alias[2]);
1547 r_alias[3] = psqrt(a_alias[3]);
1548 return r;
1549}
1550
1551template <>
1552EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2
1553prsqrt<Packet4h2>(const Packet4h2& a) {
1554 Packet4h2 r;
1555 half2* r_alias = reinterpret_cast<half2*>(&r);
1556 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1557 r_alias[0] = prsqrt(a_alias[0]);
1558 r_alias[1] = prsqrt(a_alias[1]);
1559 r_alias[2] = prsqrt(a_alias[2]);
1560 r_alias[3] = prsqrt(a_alias[3]);
1561 return r;
1562}
1563
1564// The following specialized padd, pmul, pdiv, pmin, pmax, pset1 are needed for
1565// the implementation of GPU half reduction.
1566template<>
1567EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2& a,
1568 const half2& b) {
1569#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1570 return __hadd2(a, b);
1571#else
1572 float a1 = __low2float(a);
1573 float a2 = __high2float(a);
1574 float b1 = __low2float(b);
1575 float b2 = __high2float(b);
1576 float r1 = a1 + b1;
1577 float r2 = a2 + b2;
1578 return __floats2half2_rn(r1, r2);
1579#endif
1580}
1581
1582template<>
1583EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2& a,
1584 const half2& b) {
1585#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1586 return __hmul2(a, b);
1587#else
1588 float a1 = __low2float(a);
1589 float a2 = __high2float(a);
1590 float b1 = __low2float(b);
1591 float b2 = __high2float(b);
1592 float r1 = a1 * b1;
1593 float r2 = a2 * b2;
1594 return __floats2half2_rn(r1, r2);
1595#endif
1596}
1597
1598template<>
1599EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2& a,
1600 const half2& b) {
1601#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
1602 return __h2div(a, b);
1603#else
1604 float a1 = __low2float(a);
1605 float a2 = __high2float(a);
1606 float b1 = __low2float(b);
1607 float b2 = __high2float(b);
1608 float r1 = a1 / b1;
1609 float r2 = a2 / b2;
1610 return __floats2half2_rn(r1, r2);
1611#endif
1612}
1613
1614template<>
1615EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a,
1616 const half2& b) {
1617 float a1 = __low2float(a);
1618 float a2 = __high2float(a);
1619 float b1 = __low2float(b);
1620 float b2 = __high2float(b);
1621 __half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
1622 __half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
1623 return __halves2half2(r1, r2);
1624}
1625
1626template<>
1627EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a,
1628 const half2& b) {
1629 float a1 = __low2float(a);
1630 float a2 = __high2float(a);
1631 float b1 = __low2float(b);
1632 float b2 = __high2float(b);
1633 __half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
1634 __half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
1635 return __halves2half2(r1, r2);
1636}
1637
1638#endif // (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
1639
1640#undef EIGEN_GPU_HAS_LDG
1641#undef EIGEN_CUDA_HAS_FP16_ARITHMETIC
1642#undef EIGEN_GPU_HAS_FP16_ARITHMETIC
1643
1644} // end namespace internal
1645
1646} // end namespace Eigen
1647
1648
1649#endif // EIGEN_PACKET_MATH_GPU_H
@ Aligned16
Definition Constants.h:235
GLM_FUNC_DECL T fmax(T a, T b)
Definition scalar_common.inl:76
GLM_FUNC_DECL T fmin(T a, T b)
Definition scalar_common.inl:31
vec< 4, float, highp > float4
single-qualifier floating-point vector with 4 components. (From GLM_GTX_compatibility extension)
Definition compatibility.hpp:101
vec< 2, double, highp > double2
double-qualifier floating-point vector with 2 components. (From GLM_GTX_compatibility extension)
Definition compatibility.hpp:115
Namespace containing all symbols from the Eigen library.
Definition common.h:81
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:74
Definition Half.h:142