blob: 6d4230aa7a3ec5f9b637dc449ecb0475663a185e [file] [log] [blame]
Benoit Steiner95a430a2014-10-03 19:45:19 -07001// 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
Deven Desai876f3922018-07-11 10:39:54 -040010#ifndef EIGEN_PACKET_MATH_GPU_H
11#define EIGEN_PACKET_MATH_GPU_H
Benoit Steiner95a430a2014-10-03 19:45:19 -070012
Antonio Sánchez6e4d5d42023-08-21 16:25:22 +000013// IWYU pragma: private
Rasmus Munk Larsend7d0bf82021-09-10 19:12:26 +000014#include "../../InternalHeaderCheck.h"
15
Benoit Steiner95a430a2014-10-03 19:45:19 -070016namespace Eigen {
17
18namespace internal {
19
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -080020// Read-only data cached load available.
Antonio Sanchezdb5691f2021-02-19 08:52:31 -080021#if defined(EIGEN_HIP_DEVICE_COMPILE) || (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 350)
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -080022#define EIGEN_GPU_HAS_LDG 1
23#endif
24
25// FP16 math available.
Antonio Sanchezdb5691f2021-02-19 08:52:31 -080026#if (defined(EIGEN_CUDA_ARCH) && EIGEN_CUDA_ARCH >= 530)
27#define EIGEN_CUDA_HAS_FP16_ARITHMETIC 1
28#endif
29
30#if defined(EIGEN_HIP_DEVICE_COMPILE) || defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -080031#define EIGEN_GPU_HAS_FP16_ARITHMETIC 1
32#endif
33
Benoit Steiner95a430a2014-10-03 19:45:19 -070034// Make sure this is only available when targeting a GPU: we don't want to
35// introduce conflicts between these packet_traits definitions and the ones
36// we'll use on the host side (SSE, AVX, ...)
Deven Desai876f3922018-07-11 10:39:54 -040037#if defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -080038
Tobias Woodf38e16c2023-11-29 11:12:48 +000039template <>
40struct is_arithmetic<float4> {
41 enum { value = true };
42};
43template <>
44struct is_arithmetic<double2> {
45 enum { value = true };
46};
Benoit Steiner95a430a2014-10-03 19:45:19 -070047
Tobias Woodf38e16c2023-11-29 11:12:48 +000048template <>
49struct packet_traits<float> : default_packet_traits {
Benoit Steiner95a430a2014-10-03 19:45:19 -070050 typedef float4 type;
51 typedef float4 half;
52 enum {
53 Vectorizable = 1,
54 AlignedOnScalar = 1,
Tobias Woodf38e16c2023-11-29 11:12:48 +000055 size = 4,
Benoit Steiner95a430a2014-10-03 19:45:19 -070056
Tobias Woodf38e16c2023-11-29 11:12:48 +000057 HasDiv = 1,
58 HasSin = 0,
59 HasCos = 0,
60 HasLog = 1,
61 HasExp = 1,
Benoit Steiner95a430a2014-10-03 19:45:19 -070062 HasSqrt = 1,
63 HasRsqrt = 1,
Eugene Brevdofa4f9332015-12-07 15:24:49 -080064 HasLGamma = 1,
Eugene Brevdof7362772015-12-24 21:15:38 -080065 HasDiGamma = 1,
Till Hoffmanndd5d3902016-04-01 13:32:29 +010066 HasZeta = 1,
Till Hoffmann57239f42016-04-01 14:35:21 +010067 HasPolygamma = 1,
Eugene Brevdofa4f9332015-12-07 15:24:49 -080068 HasErf = 1,
69 HasErfc = 1,
Srinivas Vasudevan18ceb342019-08-12 19:26:29 -040070 HasNdtri = 1,
Srinivas Vasudevan6e215cf2019-09-14 12:16:47 -040071 HasBessel = 1,
Eugene Brevdo39baff82016-06-02 17:04:19 -070072 HasIGamma = 1,
Michael Figurnov4bd158f2018-06-06 18:49:26 +010073 HasIGammaDerA = 1,
74 HasGammaSampleDerAlpha = 1,
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -080075 HasIGammac = 1,
Eugene Brevdo39baff82016-06-02 17:04:19 -070076 HasBetaInc = 1,
Charles Schlosserfb95e902024-04-29 23:45:49 +000077 HasBlend = 0
Benoit Steiner95a430a2014-10-03 19:45:19 -070078 };
79};
80
Tobias Woodf38e16c2023-11-29 11:12:48 +000081template <>
82struct packet_traits<double> : default_packet_traits {
Benoit Steiner95a430a2014-10-03 19:45:19 -070083 typedef double2 type;
84 typedef double2 half;
85 enum {
86 Vectorizable = 1,
87 AlignedOnScalar = 1,
Tobias Woodf38e16c2023-11-29 11:12:48 +000088 size = 2,
Benoit Steiner95a430a2014-10-03 19:45:19 -070089
Tobias Woodf38e16c2023-11-29 11:12:48 +000090 HasDiv = 1,
91 HasLog = 1,
92 HasExp = 1,
Benoit Steiner95a430a2014-10-03 19:45:19 -070093 HasSqrt = 1,
94 HasRsqrt = 1,
Eugene Brevdofa4f9332015-12-07 15:24:49 -080095 HasLGamma = 1,
Eugene Brevdof7362772015-12-24 21:15:38 -080096 HasDiGamma = 1,
Eugene Brevdo39baff82016-06-02 17:04:19 -070097 HasZeta = 1,
98 HasPolygamma = 1,
Eugene Brevdofa4f9332015-12-07 15:24:49 -080099 HasErf = 1,
100 HasErfc = 1,
Srinivas Vasudevan18ceb342019-08-12 19:26:29 -0400101 HasNdtri = 1,
Srinivas Vasudevan6e215cf2019-09-14 12:16:47 -0400102 HasBessel = 1,
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800103 HasIGamma = 1,
Michael Figurnov4bd158f2018-06-06 18:49:26 +0100104 HasIGammaDerA = 1,
105 HasGammaSampleDerAlpha = 1,
Eugene Brevdo7ea35bf2016-03-03 19:39:41 -0800106 HasIGammac = 1,
Eugene Brevdo39baff82016-06-02 17:04:19 -0700107 HasBetaInc = 1,
Benoit Steiner95a430a2014-10-03 19:45:19 -0700108 HasBlend = 0,
109 };
110};
111
Tobias Woodf38e16c2023-11-29 11:12:48 +0000112template <>
113struct unpacket_traits<float4> {
114 typedef float type;
115 enum {
116 size = 4,
117 alignment = Aligned16,
118 vectorizable = true,
119 masked_load_available = false,
120 masked_store_available = false
121 };
122 typedef float4 half;
123};
124template <>
125struct unpacket_traits<double2> {
126 typedef double type;
127 enum {
128 size = 2,
129 alignment = Aligned16,
130 vectorizable = true,
131 masked_load_available = false,
132 masked_store_available = false
133 };
134 typedef double2 half;
135};
Benoit Steiner95a430a2014-10-03 19:45:19 -0700136
Tobias Woodf38e16c2023-11-29 11:12:48 +0000137template <>
138EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pset1<float4>(const float& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700139 return make_float4(from, from, from, from);
140}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000141template <>
142EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pset1<double2>(const double& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700143 return make_double2(from, from);
144}
145
Rasmus Munk Larsenb8f8dac2019-06-20 16:18:37 -0700146// We need to distinguish ‘clang as the CUDA compiler’ from ‘clang as the host compiler,
147// invoked by NVCC’ (e.g. on MacOS). The former needs to see both host and device implementation
Rasmus Munk Larsenc9394d72019-06-20 16:23:19 -0700148// of the functions, while the latter can only deal with one of them.
Deven Desaic49f0d82019-12-10 22:14:05 +0000149#if defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG && !EIGEN_COMP_NVCC)
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800150
Tobias Woodf38e16c2023-11-29 11:12:48 +0000151EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_and(const float& a, const float& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800152 return __int_as_float(__float_as_int(a) & __float_as_int(b));
153}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000154EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_and(const double& a, const double& b) {
155 return __longlong_as_double(__double_as_longlong(a) & __double_as_longlong(b));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800156}
157
Tobias Woodf38e16c2023-11-29 11:12:48 +0000158EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_or(const float& a, const float& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800159 return __int_as_float(__float_as_int(a) | __float_as_int(b));
160}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000161EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_or(const double& a, const double& b) {
162 return __longlong_as_double(__double_as_longlong(a) | __double_as_longlong(b));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800163}
164
Tobias Woodf38e16c2023-11-29 11:12:48 +0000165EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_xor(const float& a, const float& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800166 return __int_as_float(__float_as_int(a) ^ __float_as_int(b));
167}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000168EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_xor(const double& a, const double& b) {
169 return __longlong_as_double(__double_as_longlong(a) ^ __double_as_longlong(b));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800170}
171
Tobias Woodf38e16c2023-11-29 11:12:48 +0000172EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float bitwise_andnot(const float& a, const float& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800173 return __int_as_float(__float_as_int(a) & ~__float_as_int(b));
174}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000175EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double bitwise_andnot(const double& a, const double& b) {
176 return __longlong_as_double(__double_as_longlong(a) & ~__double_as_longlong(b));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800177}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000178EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float eq_mask(const float& a, const float& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800179 return __int_as_float(a == b ? 0xffffffffu : 0u);
180}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000181EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double eq_mask(const double& a, const double& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800182 return __longlong_as_double(a == b ? 0xffffffffffffffffull : 0ull);
183}
184
Tobias Woodf38e16c2023-11-29 11:12:48 +0000185EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float lt_mask(const float& a, const float& b) {
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000186 return __int_as_float(a < b ? 0xffffffffu : 0u);
187}
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700188
Tobias Woodf38e16c2023-11-29 11:12:48 +0000189EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double lt_mask(const double& a, const double& b) {
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000190 return __longlong_as_double(a < b ? 0xffffffffffffffffull : 0ull);
191}
192
Tobias Woodf38e16c2023-11-29 11:12:48 +0000193EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float le_mask(const float& a, const float& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700194 return __int_as_float(a <= b ? 0xffffffffu : 0u);
195}
196
Tobias Woodf38e16c2023-11-29 11:12:48 +0000197EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double le_mask(const double& a, const double& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700198 return __longlong_as_double(a <= b ? 0xffffffffffffffffull : 0ull);
199}
200
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800201template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000202EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pand<float4>(const float4& a, const float4& b) {
203 return make_float4(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y), bitwise_and(a.z, b.z), bitwise_and(a.w, b.w));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800204}
205template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000206EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pand<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800207 return make_double2(bitwise_and(a.x, b.x), bitwise_and(a.y, b.y));
208}
209
210template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000211EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 por<float4>(const float4& a, const float4& b) {
212 return make_float4(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y), bitwise_or(a.z, b.z), bitwise_or(a.w, b.w));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800213}
214template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000215EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 por<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800216 return make_double2(bitwise_or(a.x, b.x), bitwise_or(a.y, b.y));
217}
218
219template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000220EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pxor<float4>(const float4& a, const float4& b) {
221 return make_float4(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y), bitwise_xor(a.z, b.z), bitwise_xor(a.w, b.w));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800222}
223template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000224EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pxor<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800225 return make_double2(bitwise_xor(a.x, b.x), bitwise_xor(a.y, b.y));
226}
227
228template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000229EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pandnot<float4>(const float4& a, const float4& b) {
230 return make_float4(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y), bitwise_andnot(a.z, b.z),
231 bitwise_andnot(a.w, b.w));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800232}
233template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000234EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pandnot<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800235 return make_double2(bitwise_andnot(a.x, b.x), bitwise_andnot(a.y, b.y));
236}
237
238template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000239EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_eq<float4>(const float4& a, const float4& b) {
240 return make_float4(eq_mask(a.x, b.x), eq_mask(a.y, b.y), eq_mask(a.z, b.z), eq_mask(a.w, b.w));
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800241}
242template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000243EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_lt<float4>(const float4& a, const float4& b) {
244 return make_float4(lt_mask(a.x, b.x), lt_mask(a.y, b.y), lt_mask(a.z, b.z), lt_mask(a.w, b.w));
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000245}
246template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000247EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pcmp_le<float4>(const float4& a, const float4& b) {
248 return make_float4(le_mask(a.x, b.x), le_mask(a.y, b.y), le_mask(a.z, b.z), le_mask(a.w, b.w));
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700249}
250template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000251EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pcmp_eq<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsen2eccbaf2019-01-17 17:45:08 -0800252 return make_double2(eq_mask(a.x, b.x), eq_mask(a.y, b.y));
253}
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000254template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000255EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pcmp_lt<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000256 return make_double2(lt_mask(a.x, b.x), lt_mask(a.y, b.y));
257}
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700258template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000259EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pcmp_le<double2>(const double2& a, const double2& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700260 return make_double2(le_mask(a.x, b.x), le_mask(a.y, b.y));
261}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000262#endif // defined(EIGEN_CUDA_ARCH) || defined(EIGEN_HIPCC) || (defined(EIGEN_CUDACC) && EIGEN_COMP_CLANG &&
263 // !EIGEN_COMP_NVCC)
Benoit Steiner95a430a2014-10-03 19:45:19 -0700264
Tobias Woodf38e16c2023-11-29 11:12:48 +0000265template <>
266EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 plset<float4>(const float& a) {
267 return make_float4(a, a + 1, a + 2, a + 3);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700268}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000269template <>
270EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 plset<double2>(const double& a) {
271 return make_double2(a, a + 1);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700272}
273
Tobias Woodf38e16c2023-11-29 11:12:48 +0000274template <>
275EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 padd<float4>(const float4& a, const float4& b) {
276 return make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700277}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000278template <>
279EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 padd<double2>(const double2& a, const double2& b) {
280 return make_double2(a.x + b.x, a.y + b.y);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700281}
282
Tobias Woodf38e16c2023-11-29 11:12:48 +0000283template <>
284EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 psub<float4>(const float4& a, const float4& b) {
285 return make_float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700286}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000287template <>
288EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 psub<double2>(const double2& a, const double2& b) {
289 return make_double2(a.x - b.x, a.y - b.y);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700290}
291
Tobias Woodf38e16c2023-11-29 11:12:48 +0000292template <>
293EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pnegate(const float4& a) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700294 return make_float4(-a.x, -a.y, -a.z, -a.w);
295}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000296template <>
297EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pnegate(const double2& a) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700298 return make_double2(-a.x, -a.y);
299}
300
Tobias Woodf38e16c2023-11-29 11:12:48 +0000301template <>
302EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pconj(const float4& a) {
303 return a;
Benoit Steiner95a430a2014-10-03 19:45:19 -0700304}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000305template <>
306EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pconj(const double2& a) {
307 return a;
Benoit Steiner95a430a2014-10-03 19:45:19 -0700308}
309
Tobias Woodf38e16c2023-11-29 11:12:48 +0000310template <>
311EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmul<float4>(const float4& a, const float4& b) {
312 return make_float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700313}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000314template <>
315EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmul<double2>(const double2& a, const double2& b) {
316 return make_double2(a.x * b.x, a.y * b.y);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700317}
318
Tobias Woodf38e16c2023-11-29 11:12:48 +0000319template <>
320EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pdiv<float4>(const float4& a, const float4& b) {
321 return make_float4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
322}
323template <>
324EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pdiv<double2>(const double2& a, const double2& b) {
325 return make_double2(a.x / b.x, a.y / b.y);
326}
327
328template <>
329EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmin<float4>(const float4& a, const float4& b) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700330 return make_float4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w));
331}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000332template <>
333EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmin<double2>(const double2& a, const double2& b) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700334 return make_double2(fmin(a.x, b.x), fmin(a.y, b.y));
335}
336
Tobias Woodf38e16c2023-11-29 11:12:48 +0000337template <>
338EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pmax<float4>(const float4& a, const float4& b) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700339 return make_float4(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z), fmaxf(a.w, b.w));
340}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000341template <>
342EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pmax<double2>(const double2& a, const double2& b) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700343 return make_double2(fmax(a.x, b.x), fmax(a.y, b.y));
344}
345
Tobias Woodf38e16c2023-11-29 11:12:48 +0000346template <>
347EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 pload<float4>(const float* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700348 return *reinterpret_cast<const float4*>(from);
349}
350
Tobias Woodf38e16c2023-11-29 11:12:48 +0000351template <>
352EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 pload<double2>(const double* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700353 return *reinterpret_cast<const double2*>(from);
354}
355
Tobias Woodf38e16c2023-11-29 11:12:48 +0000356template <>
357EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploadu<float4>(const float* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700358 return make_float4(from[0], from[1], from[2], from[3]);
359}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000360template <>
361EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploadu<double2>(const double* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700362 return make_double2(from[0], from[1]);
363}
364
Tobias Woodf38e16c2023-11-29 11:12:48 +0000365template <>
366EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float4 ploaddup<float4>(const float* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700367 return make_float4(from[0], from[0], from[1], from[1]);
368}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000369template <>
370EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double2 ploaddup<double2>(const double* from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700371 return make_double2(from[0], from[0]);
372}
373
Tobias Woodf38e16c2023-11-29 11:12:48 +0000374template <>
375EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<float>(float* to, const float4& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700376 *reinterpret_cast<float4*>(to) = from;
377}
378
Tobias Woodf38e16c2023-11-29 11:12:48 +0000379template <>
380EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<double>(double* to, const double2& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700381 *reinterpret_cast<double2*>(to) = from;
382}
383
Tobias Woodf38e16c2023-11-29 11:12:48 +0000384template <>
385EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const float4& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700386 to[0] = from.x;
387 to[1] = from.y;
388 to[2] = from.z;
389 to[3] = from.w;
390}
391
Tobias Woodf38e16c2023-11-29 11:12:48 +0000392template <>
393EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<double>(double* to, const double2& from) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700394 to[0] = from.x;
395 to[1] = from.y;
396}
397
Tobias Woodf38e16c2023-11-29 11:12:48 +0000398template <>
Benoit Steiner95a430a2014-10-03 19:45:19 -0700399EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Aligned>(const float* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800400#if defined(EIGEN_GPU_HAS_LDG)
Antonio Sánchezf6cc3592023-02-03 19:18:45 +0000401 return __ldg(reinterpret_cast<const float4*>(from));
Benoit Steiner51be91f2015-12-21 08:42:58 -0800402#else
403 return make_float4(from[0], from[1], from[2], from[3]);
404#endif
Benoit Steiner95a430a2014-10-03 19:45:19 -0700405}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000406template <>
Benoit Steiner95a430a2014-10-03 19:45:19 -0700407EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Aligned>(const double* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800408#if defined(EIGEN_GPU_HAS_LDG)
Antonio Sánchezf6cc3592023-02-03 19:18:45 +0000409 return __ldg(reinterpret_cast<const double2*>(from));
Benoit Steiner51be91f2015-12-21 08:42:58 -0800410#else
Benoit Steinera6c24362015-12-21 09:05:45 -0800411 return make_double2(from[0], from[1]);
Benoit Steiner51be91f2015-12-21 08:42:58 -0800412#endif
Benoit Steiner95a430a2014-10-03 19:45:19 -0700413}
414
Tobias Woodf38e16c2023-11-29 11:12:48 +0000415template <>
Benoit Steiner95a430a2014-10-03 19:45:19 -0700416EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE float4 ploadt_ro<float4, Unaligned>(const float* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800417#if defined(EIGEN_GPU_HAS_LDG)
Tobias Woodf38e16c2023-11-29 11:12:48 +0000418 return make_float4(__ldg(from + 0), __ldg(from + 1), __ldg(from + 2), __ldg(from + 3));
Benoit Steiner51be91f2015-12-21 08:42:58 -0800419#else
420 return make_float4(from[0], from[1], from[2], from[3]);
421#endif
Benoit Steiner95a430a2014-10-03 19:45:19 -0700422}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000423template <>
Benoit Steiner95a430a2014-10-03 19:45:19 -0700424EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE double2 ploadt_ro<double2, Unaligned>(const double* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800425#if defined(EIGEN_GPU_HAS_LDG)
Tobias Woodf38e16c2023-11-29 11:12:48 +0000426 return make_double2(__ldg(from + 0), __ldg(from + 1));
Benoit Steiner51be91f2015-12-21 08:42:58 -0800427#else
Benoit Steinera6c24362015-12-21 09:05:45 -0800428 return make_double2(from[0], from[1]);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700429#endif
Benoit Steiner51be91f2015-12-21 08:42:58 -0800430}
Benoit Steiner95a430a2014-10-03 19:45:19 -0700431
Tobias Woodf38e16c2023-11-29 11:12:48 +0000432template <>
433EIGEN_DEVICE_FUNC inline float4 pgather<float, float4>(const float* from, Index stride) {
434 return make_float4(from[0 * stride], from[1 * stride], from[2 * stride], from[3 * stride]);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700435}
436
Tobias Woodf38e16c2023-11-29 11:12:48 +0000437template <>
438EIGEN_DEVICE_FUNC inline double2 pgather<double, double2>(const double* from, Index stride) {
439 return make_double2(from[0 * stride], from[1 * stride]);
Benoit Steiner95a430a2014-10-03 19:45:19 -0700440}
441
Tobias Woodf38e16c2023-11-29 11:12:48 +0000442template <>
443EIGEN_DEVICE_FUNC inline void pscatter<float, float4>(float* to, const float4& from, Index stride) {
444 to[stride * 0] = from.x;
445 to[stride * 1] = from.y;
446 to[stride * 2] = from.z;
447 to[stride * 3] = from.w;
Benoit Steiner95a430a2014-10-03 19:45:19 -0700448}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000449template <>
450EIGEN_DEVICE_FUNC inline void pscatter<double, double2>(double* to, const double2& from, Index stride) {
451 to[stride * 0] = from.x;
452 to[stride * 1] = from.y;
Benoit Steiner95a430a2014-10-03 19:45:19 -0700453}
454
Tobias Woodf38e16c2023-11-29 11:12:48 +0000455template <>
456EIGEN_DEVICE_FUNC inline float pfirst<float4>(const float4& a) {
Benoit Steiner1946cc42014-10-30 17:52:32 -0700457 return a.x;
458}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000459template <>
460EIGEN_DEVICE_FUNC inline double pfirst<double2>(const double2& a) {
Benoit Steiner1946cc42014-10-30 17:52:32 -0700461 return a.x;
462}
463
Tobias Woodf38e16c2023-11-29 11:12:48 +0000464template <>
465EIGEN_DEVICE_FUNC inline float predux<float4>(const float4& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800466 return a.x + a.y + a.z + a.w;
467}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000468template <>
469EIGEN_DEVICE_FUNC inline double predux<double2>(const double2& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800470 return a.x + a.y;
471}
472
Tobias Woodf38e16c2023-11-29 11:12:48 +0000473template <>
474EIGEN_DEVICE_FUNC inline float predux_max<float4>(const float4& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800475 return fmaxf(fmaxf(a.x, a.y), fmaxf(a.z, a.w));
476}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000477template <>
478EIGEN_DEVICE_FUNC inline double predux_max<double2>(const double2& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800479 return fmax(a.x, a.y);
480}
481
Tobias Woodf38e16c2023-11-29 11:12:48 +0000482template <>
483EIGEN_DEVICE_FUNC inline float predux_min<float4>(const float4& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800484 return fminf(fminf(a.x, a.y), fminf(a.z, a.w));
485}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000486template <>
487EIGEN_DEVICE_FUNC inline double predux_min<double2>(const double2& a) {
Benoit Steiner509e4dd2014-11-19 10:34:11 -0800488 return fmin(a.x, a.y);
489}
490
Tobias Woodf38e16c2023-11-29 11:12:48 +0000491template <>
492EIGEN_DEVICE_FUNC inline float predux_mul<float4>(const float4& a) {
Benoit Steiner98f8f0d2015-09-08 15:37:25 -0700493 return a.x * a.y * a.z * a.w;
494}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000495template <>
496EIGEN_DEVICE_FUNC inline double predux_mul<double2>(const double2& a) {
Benoit Steiner98f8f0d2015-09-08 15:37:25 -0700497 return a.x * a.y;
498}
499
Tobias Woodf38e16c2023-11-29 11:12:48 +0000500template <>
501EIGEN_DEVICE_FUNC inline float4 pabs<float4>(const float4& a) {
Benoit Steinerabdbe852015-03-24 10:45:46 -0700502 return make_float4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w));
Benoit Steiner1946cc42014-10-30 17:52:32 -0700503}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000504template <>
505EIGEN_DEVICE_FUNC inline double2 pabs<double2>(const double2& a) {
Benoit Steinerabdbe852015-03-24 10:45:46 -0700506 return make_double2(fabs(a.x), fabs(a.y));
Benoit Steiner1946cc42014-10-30 17:52:32 -0700507}
508
Tobias Woodf38e16c2023-11-29 11:12:48 +0000509template <>
510EIGEN_DEVICE_FUNC inline float4 pfloor<float4>(const float4& a) {
Rasmus Munk Larsen4d7f3172019-02-21 13:32:13 -0800511 return make_float4(floorf(a.x), floorf(a.y), floorf(a.z), floorf(a.w));
512}
Tobias Woodf38e16c2023-11-29 11:12:48 +0000513template <>
514EIGEN_DEVICE_FUNC inline double2 pfloor<double2>(const double2& a) {
Rasmus Munk Larsen4d7f3172019-02-21 13:32:13 -0800515 return make_double2(floor(a.x), floor(a.y));
516}
517
Rasmus Munk Larsen9000b372024-04-30 22:18:25 +0000518template <>
519EIGEN_DEVICE_FUNC inline float4 pceil<float4>(const float4& a) {
520 return make_float4(ceilf(a.x), ceilf(a.y), ceilf(a.z), ceilf(a.w));
521}
522template <>
523EIGEN_DEVICE_FUNC inline double2 pceil<double2>(const double2& a) {
524 return make_double2(ceil(a.x), ceil(a.y));
525}
526
527template <>
528EIGEN_DEVICE_FUNC inline float4 print<float4>(const float4& a) {
529 return make_float4(rintf(a.x), rintf(a.y), rintf(a.z), rintf(a.w));
530}
531template <>
532EIGEN_DEVICE_FUNC inline double2 print<double2>(const double2& a) {
533 return make_double2(rint(a.x), rint(a.y));
534}
535
536template <>
537EIGEN_DEVICE_FUNC inline float4 ptrunc<float4>(const float4& a) {
538 return make_float4(truncf(a.x), truncf(a.y), truncf(a.z), truncf(a.w));
539}
540template <>
541EIGEN_DEVICE_FUNC inline double2 ptrunc<double2>(const double2& a) {
542 return make_double2(trunc(a.x), trunc(a.y));
543}
544
Tobias Woodf38e16c2023-11-29 11:12:48 +0000545EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<float4, 4>& kernel) {
Benoit Steiner34d9fce2017-02-27 16:33:33 -0800546 float tmp = kernel.packet[0].y;
Benoit Steiner95a430a2014-10-03 19:45:19 -0700547 kernel.packet[0].y = kernel.packet[1].x;
548 kernel.packet[1].x = tmp;
549
550 tmp = kernel.packet[0].z;
551 kernel.packet[0].z = kernel.packet[2].x;
552 kernel.packet[2].x = tmp;
553
554 tmp = kernel.packet[0].w;
555 kernel.packet[0].w = kernel.packet[3].x;
556 kernel.packet[3].x = tmp;
557
558 tmp = kernel.packet[1].z;
559 kernel.packet[1].z = kernel.packet[2].y;
560 kernel.packet[2].y = tmp;
561
562 tmp = kernel.packet[1].w;
563 kernel.packet[1].w = kernel.packet[3].y;
564 kernel.packet[3].y = tmp;
565
566 tmp = kernel.packet[2].w;
567 kernel.packet[2].w = kernel.packet[3].z;
568 kernel.packet[3].z = tmp;
569}
570
Tobias Woodf38e16c2023-11-29 11:12:48 +0000571EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<double2, 2>& kernel) {
Benoit Steiner95a430a2014-10-03 19:45:19 -0700572 double tmp = kernel.packet[0].y;
573 kernel.packet[0].y = kernel.packet[1].x;
574 kernel.packet[1].x = tmp;
575}
576
Tobias Woodf38e16c2023-11-29 11:12:48 +0000577#endif // defined(EIGEN_GPUCC) && defined(EIGEN_USE_GPU)
Benoit Steiner95a430a2014-10-03 19:45:19 -0700578
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700579// Half-packet functions are not available on the host for CUDA 9.0-9.2, only
580// on device. There is no benefit to using them on the host anyways, since they are
581// emulated.
582#if (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700583
Sami Kamab733b8b2020-03-10 20:28:43 +0000584typedef ulonglong2 Packet4h2;
Tobias Woodf38e16c2023-11-29 11:12:48 +0000585template <>
586struct unpacket_traits<Packet4h2> {
587 typedef Eigen::half type;
588 enum {
589 size = 8,
590 alignment = Aligned16,
591 vectorizable = true,
592 masked_load_available = false,
593 masked_store_available = false
594 };
595 typedef Packet4h2 half;
596};
597template <>
598struct is_arithmetic<Packet4h2> {
599 enum { value = true };
600};
Sami Kamab733b8b2020-03-10 20:28:43 +0000601
Tobias Woodf38e16c2023-11-29 11:12:48 +0000602template <>
603struct unpacket_traits<half2> {
604 typedef Eigen::half type;
605 enum {
606 size = 2,
607 alignment = Aligned16,
608 vectorizable = true,
609 masked_load_available = false,
610 masked_store_available = false
611 };
612 typedef half2 half;
613};
614template <>
615struct is_arithmetic<half2> {
616 enum { value = true };
617};
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700618
Tobias Woodf38e16c2023-11-29 11:12:48 +0000619template <>
620struct packet_traits<Eigen::half> : default_packet_traits {
Sami Kamab733b8b2020-03-10 20:28:43 +0000621 typedef Packet4h2 type;
622 typedef Packet4h2 half;
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700623 enum {
624 Vectorizable = 1,
625 AlignedOnScalar = 1,
Tobias Woodf38e16c2023-11-29 11:12:48 +0000626 size = 8,
627 HasAdd = 1,
628 HasSub = 1,
629 HasMul = 1,
630 HasDiv = 1,
631 HasSqrt = 1,
632 HasRsqrt = 1,
633 HasExp = 1,
634 HasExpm1 = 1,
635 HasLog = 1,
636 HasLog1p = 1
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700637 };
638};
639
Tobias Woodf38e16c2023-11-29 11:12:48 +0000640template <>
Sami Kamab733b8b2020-03-10 20:28:43 +0000641EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pset1<half2>(const Eigen::half& from) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700642 return __half2half2(from);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700643}
644
Sami Kamab733b8b2020-03-10 20:28:43 +0000645template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +0000646EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pset1<Packet4h2>(const Eigen::half& from) {
Sami Kamab733b8b2020-03-10 20:28:43 +0000647 Packet4h2 r;
648 half2* p_alias = reinterpret_cast<half2*>(&r);
649 p_alias[0] = pset1<half2>(from);
650 p_alias[1] = pset1<half2>(from);
651 p_alias[2] = pset1<half2>(from);
652 p_alias[3] = pset1<half2>(from);
653 return r;
654}
655
Sami Kamab733b8b2020-03-10 20:28:43 +0000656namespace {
657
658EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pload(const Eigen::half* from) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700659 return *reinterpret_cast<const half2*>(from);
660}
661
Tobias Woodf38e16c2023-11-29 11:12:48 +0000662EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploadu(const Eigen::half* from) { return __halves2half2(from[0], from[1]); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700663
Tobias Woodf38e16c2023-11-29 11:12:48 +0000664EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ploaddup(const Eigen::half* from) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700665 return __halves2half2(from[0], from[0]);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700666}
667
Tobias Woodf38e16c2023-11-29 11:12:48 +0000668EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore(Eigen::half* to, const half2& from) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700669 *reinterpret_cast<half2*>(to) = from;
670}
671
Tobias Woodf38e16c2023-11-29 11:12:48 +0000672EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu(Eigen::half* to, const half2& from) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700673 to[0] = __low2half(from);
674 to[1] = __high2half(from);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700675}
676
Tobias Woodf38e16c2023-11-29 11:12:48 +0000677EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_aligned(const Eigen::half* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800678#if defined(EIGEN_GPU_HAS_LDG)
Antonio Sanchezdb5691f2021-02-19 08:52:31 -0800679 // Input is guaranteed to be properly aligned.
680 return __ldg(reinterpret_cast<const half2*>(from));
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700681#else
Tobias Woodf38e16c2023-11-29 11:12:48 +0000682 return __halves2half2(*(from + 0), *(from + 1));
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700683#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700684}
685
Tobias Woodf38e16c2023-11-29 11:12:48 +0000686EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE half2 ploadt_ro_unaligned(const Eigen::half* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800687#if defined(EIGEN_GPU_HAS_LDG)
Tobias Woodf38e16c2023-11-29 11:12:48 +0000688 return __halves2half2(__ldg(from + 0), __ldg(from + 1));
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700689#else
Tobias Woodf38e16c2023-11-29 11:12:48 +0000690 return __halves2half2(*(from + 0), *(from + 1));
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700691#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700692}
693
Tobias Woodf38e16c2023-11-29 11:12:48 +0000694EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pgather(const Eigen::half* from, Index stride) {
695 return __halves2half2(from[0 * stride], from[1 * stride]);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700696}
697
Tobias Woodf38e16c2023-11-29 11:12:48 +0000698EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter(Eigen::half* to, const half2& from, Index stride) {
699 to[stride * 0] = __low2half(from);
700 to[stride * 1] = __high2half(from);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700701}
702
Tobias Woodf38e16c2023-11-29 11:12:48 +0000703EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst(const half2& a) { return __low2half(a); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700704
Sami Kamab733b8b2020-03-10 20:28:43 +0000705EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pabs(const half2& a) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700706 half a1 = __low2half(a);
707 half a2 = __high2half(a);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700708 half result1 = half_impl::raw_uint16_to_half(a1.x & 0x7FFF);
709 half result2 = half_impl::raw_uint16_to_half(a2.x & 0x7FFF);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700710 return __halves2half2(result1, result2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700711}
712
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800713EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 ptrue(const half2& /*a*/) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700714 half true_half = half_impl::raw_uint16_to_half(0xffffu);
715 return pset1<half2>(true_half);
716}
717
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800718EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pzero(const half2& /*a*/) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700719 half false_half = half_impl::raw_uint16_to_half(0x0000u);
720 return pset1<half2>(false_half);
721}
722
Tobias Woodf38e16c2023-11-29 11:12:48 +0000723EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose(PacketBlock<half2, 2>& kernel) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700724 __half a1 = __low2half(kernel.packet[0]);
725 __half a2 = __high2half(kernel.packet[0]);
726 __half b1 = __low2half(kernel.packet[1]);
727 __half b2 = __high2half(kernel.packet[1]);
728 kernel.packet[0] = __halves2half2(a1, b1);
729 kernel.packet[1] = __halves2half2(a2, b2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700730}
731
Sami Kamab733b8b2020-03-10 20:28:43 +0000732EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plset(const Eigen::half& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800733#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700734 return __halves2half2(a, __hadd(a, __float2half(1.0f)));
735#else
736 float f = __half2float(a) + 1.0f;
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700737 return __halves2half2(a, __float2half(f));
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700738#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700739}
740
Tobias Woodf38e16c2023-11-29 11:12:48 +0000741EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pselect(const half2& mask, const half2& a, const half2& b) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700742 half mask_low = __low2half(mask);
743 half mask_high = __high2half(mask);
744 half result_low = mask_low == half(0) ? __low2half(b) : __low2half(a);
745 half result_high = mask_high == half(0) ? __high2half(b) : __high2half(a);
746 return __halves2half2(result_low, result_high);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700747}
748
Tobias Woodf38e16c2023-11-29 11:12:48 +0000749EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_eq(const half2& a, const half2& b) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700750 half true_half = half_impl::raw_uint16_to_half(0xffffu);
751 half false_half = half_impl::raw_uint16_to_half(0x0000u);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700752 half a1 = __low2half(a);
753 half a2 = __high2half(a);
754 half b1 = __low2half(b);
755 half b2 = __high2half(b);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700756 half eq1 = __half2float(a1) == __half2float(b1) ? true_half : false_half;
757 half eq2 = __half2float(a2) == __half2float(b2) ? true_half : false_half;
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700758 return __halves2half2(eq1, eq2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700759}
760
Tobias Woodf38e16c2023-11-29 11:12:48 +0000761EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_lt(const half2& a, const half2& b) {
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000762 half true_half = half_impl::raw_uint16_to_half(0xffffu);
763 half false_half = half_impl::raw_uint16_to_half(0x0000u);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700764 half a1 = __low2half(a);
765 half a2 = __high2half(a);
766 half b1 = __low2half(b);
767 half b2 = __high2half(b);
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000768 half eq1 = __half2float(a1) < __half2float(b1) ? true_half : false_half;
769 half eq2 = __half2float(a2) < __half2float(b2) ? true_half : false_half;
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700770 return __halves2half2(eq1, eq2);
Rasmus Munk Larsena5660742019-12-16 21:33:42 +0000771}
772
Tobias Woodf38e16c2023-11-29 11:12:48 +0000773EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pcmp_le(const half2& a, const half2& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -0700774 half true_half = half_impl::raw_uint16_to_half(0xffffu);
775 half false_half = half_impl::raw_uint16_to_half(0x0000u);
776 half a1 = __low2half(a);
777 half a2 = __high2half(a);
778 half b1 = __low2half(b);
779 half b2 = __high2half(b);
780 half eq1 = __half2float(a1) <= __half2float(b1) ? true_half : false_half;
781 half eq2 = __half2float(a2) <= __half2float(b2) ? true_half : false_half;
782 return __halves2half2(eq1, eq2);
783}
784
Tobias Woodf38e16c2023-11-29 11:12:48 +0000785EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pand(const half2& a, const half2& b) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700786 half a1 = __low2half(a);
787 half a2 = __high2half(a);
788 half b1 = __low2half(b);
789 half b2 = __high2half(b);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700790 half result1 = half_impl::raw_uint16_to_half(a1.x & b1.x);
791 half result2 = half_impl::raw_uint16_to_half(a2.x & b2.x);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700792 return __halves2half2(result1, result2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700793}
794
Tobias Woodf38e16c2023-11-29 11:12:48 +0000795EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 por(const half2& a, const half2& b) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700796 half a1 = __low2half(a);
797 half a2 = __high2half(a);
798 half b1 = __low2half(b);
799 half b2 = __high2half(b);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700800 half result1 = half_impl::raw_uint16_to_half(a1.x | b1.x);
801 half result2 = half_impl::raw_uint16_to_half(a2.x | b2.x);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700802 return __halves2half2(result1, result2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700803}
804
Tobias Woodf38e16c2023-11-29 11:12:48 +0000805EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pxor(const half2& a, const half2& b) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700806 half a1 = __low2half(a);
807 half a2 = __high2half(a);
808 half b1 = __low2half(b);
809 half b2 = __high2half(b);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700810 half result1 = half_impl::raw_uint16_to_half(a1.x ^ b1.x);
811 half result2 = half_impl::raw_uint16_to_half(a2.x ^ b2.x);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700812 return __halves2half2(result1, result2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700813}
814
Tobias Woodf38e16c2023-11-29 11:12:48 +0000815EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pandnot(const half2& a, const half2& b) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700816 half a1 = __low2half(a);
817 half a2 = __high2half(a);
818 half b1 = __low2half(b);
819 half b2 = __high2half(b);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700820 half result1 = half_impl::raw_uint16_to_half(a1.x & ~b1.x);
821 half result2 = half_impl::raw_uint16_to_half(a2.x & ~b2.x);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700822 return __halves2half2(result1, result2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700823}
824
Tobias Woodf38e16c2023-11-29 11:12:48 +0000825EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800826#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700827 return __hadd2(a, b);
828#else
829 float a1 = __low2float(a);
830 float a2 = __high2float(a);
831 float b1 = __low2float(b);
832 float b2 = __high2float(b);
833 float r1 = a1 + b1;
834 float r2 = a2 + b2;
835 return __floats2half2_rn(r1, r2);
836#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700837}
838
Tobias Woodf38e16c2023-11-29 11:12:48 +0000839EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psub(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800840#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700841 return __hsub2(a, b);
842#else
843 float a1 = __low2float(a);
844 float a2 = __high2float(a);
845 float b1 = __low2float(b);
846 float b2 = __high2float(b);
847 float r1 = a1 - b1;
848 float r2 = a2 - b2;
849 return __floats2half2_rn(r1, r2);
850#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700851}
852
Sami Kamab733b8b2020-03-10 20:28:43 +0000853EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pnegate(const half2& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800854#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700855 return __hneg2(a);
856#else
857 float a1 = __low2float(a);
858 float a2 = __high2float(a);
859 return __floats2half2_rn(-a1, -a2);
860#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700861}
862
Sami Kamab733b8b2020-03-10 20:28:43 +0000863EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pconj(const half2& a) { return a; }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700864
Tobias Woodf38e16c2023-11-29 11:12:48 +0000865EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800866#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700867 return __hmul2(a, b);
868#else
869 float a1 = __low2float(a);
870 float a2 = __high2float(a);
871 float b1 = __low2float(b);
872 float b2 = __high2float(b);
873 float r1 = a1 * b1;
874 float r2 = a2 * b2;
875 return __floats2half2_rn(r1, r2);
876#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700877}
878
Tobias Woodf38e16c2023-11-29 11:12:48 +0000879EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmadd(const half2& a, const half2& b, const half2& c) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800880#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Tobias Woodf38e16c2023-11-29 11:12:48 +0000881 return __hfma2(a, b, c);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700882#else
883 float a1 = __low2float(a);
884 float a2 = __high2float(a);
885 float b1 = __low2float(b);
886 float b2 = __high2float(b);
887 float c1 = __low2float(c);
888 float c2 = __high2float(c);
889 float r1 = a1 * b1 + c1;
890 float r2 = a2 * b2 + c2;
891 return __floats2half2_rn(r1, r2);
892#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700893}
894
Tobias Woodf38e16c2023-11-29 11:12:48 +0000895EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800896#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700897 return __h2div(a, b);
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800898#else
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700899 float a1 = __low2float(a);
900 float a2 = __high2float(a);
901 float b1 = __low2float(b);
902 float b2 = __high2float(b);
903 float r1 = a1 / b1;
904 float r2 = a2 / b2;
905 return __floats2half2_rn(r1, r2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700906#endif
907}
908
Tobias Woodf38e16c2023-11-29 11:12:48 +0000909EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin(const half2& a, const half2& b) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700910 float a1 = __low2float(a);
911 float a2 = __high2float(a);
912 float b1 = __low2float(b);
913 float b2 = __high2float(b);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700914 __half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
915 __half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
916 return __halves2half2(r1, r2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700917}
918
Tobias Woodf38e16c2023-11-29 11:12:48 +0000919EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax(const half2& a, const half2& b) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700920 float a1 = __low2float(a);
921 float a2 = __high2float(a);
922 float b1 = __low2float(b);
923 float b2 = __high2float(b);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700924 __half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
925 __half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
926 return __halves2half2(r1, r2);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700927}
928
Sami Kamab733b8b2020-03-10 20:28:43 +0000929EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux(const half2& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800930#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700931 return __hadd(__low2half(a), __high2half(a));
932#else
933 float a1 = __low2float(a);
934 float a2 = __high2float(a);
935 return Eigen::half(__float2half(a1 + a2));
936#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700937}
938
Sami Kamab733b8b2020-03-10 20:28:43 +0000939EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max(const half2& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800940#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700941 __half first = __low2half(a);
942 __half second = __high2half(a);
943 return __hgt(first, second) ? first : second;
944#else
945 float a1 = __low2float(a);
946 float a2 = __high2float(a);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700947 return a1 > a2 ? __low2half(a) : __high2half(a);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700948#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700949}
950
Sami Kamab733b8b2020-03-10 20:28:43 +0000951EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min(const half2& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800952#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700953 __half first = __low2half(a);
954 __half second = __high2half(a);
955 return __hlt(first, second) ? first : second;
956#else
957 float a1 = __low2float(a);
958 float a2 = __high2float(a);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -0700959 return a1 < a2 ? __low2half(a) : __high2half(a);
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700960#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700961}
962
Sami Kamab733b8b2020-03-10 20:28:43 +0000963EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul(const half2& a) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -0800964#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700965 return __hmul(__low2half(a), __high2half(a));
966#else
967 float a1 = __low2float(a);
968 float a2 = __high2float(a);
969 return Eigen::half(__float2half(a1 * a2));
970#endif
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700971}
972
Sami Kamab733b8b2020-03-10 20:28:43 +0000973EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog1p(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700974 float a1 = __low2float(a);
975 float a2 = __high2float(a);
976 float r1 = log1pf(a1);
977 float r2 = log1pf(a2);
978 return __floats2half2_rn(r1, r2);
979}
980
Sami Kamab733b8b2020-03-10 20:28:43 +0000981EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexpm1(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700982 float a1 = __low2float(a);
983 float a2 = __high2float(a);
984 float r1 = expm1f(a1);
985 float r2 = expm1f(a2);
986 return __floats2half2_rn(r1, r2);
987}
988
Tobias Woodf38e16c2023-11-29 11:12:48 +0000989#if (EIGEN_CUDA_SDK_VER >= 80000 && defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)) || defined(EIGEN_HIP_DEVICE_COMPILE)
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700990
Tobias Woodf38e16c2023-11-29 11:12:48 +0000991EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog(const half2& a) { return h2log(a); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700992
Tobias Woodf38e16c2023-11-29 11:12:48 +0000993EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp(const half2& a) { return h2exp(a); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700994
Tobias Woodf38e16c2023-11-29 11:12:48 +0000995EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt(const half2& a) { return h2sqrt(a); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700996
Tobias Woodf38e16c2023-11-29 11:12:48 +0000997EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt(const half2& a) { return h2rsqrt(a); }
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -0700998
999#else
1000
Sami Kamab733b8b2020-03-10 20:28:43 +00001001EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 plog(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -07001002 float a1 = __low2float(a);
1003 float a2 = __high2float(a);
1004 float r1 = logf(a1);
1005 float r2 = logf(a2);
1006 return __floats2half2_rn(r1, r2);
1007}
1008
Sami Kamab733b8b2020-03-10 20:28:43 +00001009EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pexp(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -07001010 float a1 = __low2float(a);
1011 float a2 = __high2float(a);
1012 float r1 = expf(a1);
1013 float r2 = expf(a2);
1014 return __floats2half2_rn(r1, r2);
1015}
1016
Sami Kamab733b8b2020-03-10 20:28:43 +00001017EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 psqrt(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -07001018 float a1 = __low2float(a);
1019 float a2 = __high2float(a);
1020 float r1 = sqrtf(a1);
1021 float r2 = sqrtf(a2);
1022 return __floats2half2_rn(r1, r2);
1023}
1024
Sami Kamab733b8b2020-03-10 20:28:43 +00001025EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 prsqrt(const half2& a) {
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -07001026 float a1 = __low2float(a);
1027 float a2 = __high2float(a);
1028 float r1 = rsqrtf(a1);
1029 float r2 = rsqrtf(a2);
1030 return __floats2half2_rn(r1, r2);
1031}
1032#endif
Tobias Woodf38e16c2023-11-29 11:12:48 +00001033} // namespace
Sami Kamab733b8b2020-03-10 20:28:43 +00001034
Sami Kamab733b8b2020-03-10 20:28:43 +00001035template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001036EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pload<Packet4h2>(const Eigen::half* from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001037 return *reinterpret_cast<const Packet4h2*>(from);
1038}
1039
1040// unaligned load;
1041template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001042EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 ploadu<Packet4h2>(const Eigen::half* from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001043 Packet4h2 r;
1044 half2* p_alias = reinterpret_cast<half2*>(&r);
1045 p_alias[0] = ploadu(from + 0);
1046 p_alias[1] = ploadu(from + 2);
1047 p_alias[2] = ploadu(from + 4);
1048 p_alias[3] = ploadu(from + 6);
1049 return r;
1050}
1051
1052template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001053EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 ploaddup<Packet4h2>(const Eigen::half* from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001054 Packet4h2 r;
1055 half2* p_alias = reinterpret_cast<half2*>(&r);
1056 p_alias[0] = ploaddup(from + 0);
1057 p_alias[1] = ploaddup(from + 1);
1058 p_alias[2] = ploaddup(from + 2);
1059 p_alias[3] = ploaddup(from + 3);
1060 return r;
1061}
1062
1063template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001064EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstore<Eigen::half>(Eigen::half* to, const Packet4h2& from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001065 *reinterpret_cast<Packet4h2*>(to) = from;
1066}
1067
1068template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001069EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(Eigen::half* to, const Packet4h2& from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001070 const half2* from_alias = reinterpret_cast<const half2*>(&from);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001071 pstoreu(to + 0, from_alias[0]);
1072 pstoreu(to + 2, from_alias[1]);
1073 pstoreu(to + 4, from_alias[2]);
1074 pstoreu(to + 6, from_alias[3]);
Sami Kamab733b8b2020-03-10 20:28:43 +00001075}
1076
1077template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001078EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2 ploadt_ro<Packet4h2, Aligned>(const Eigen::half* from) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001079#if defined(EIGEN_GPU_HAS_LDG)
Sami Kamab733b8b2020-03-10 20:28:43 +00001080 Packet4h2 r;
Antonio Sanchezdb5691f2021-02-19 08:52:31 -08001081 r = __ldg(reinterpret_cast<const Packet4h2*>(from));
Sami Kamab733b8b2020-03-10 20:28:43 +00001082 return r;
1083#else
1084 Packet4h2 r;
1085 half2* r_alias = reinterpret_cast<half2*>(&r);
1086 r_alias[0] = ploadt_ro_aligned(from + 0);
1087 r_alias[1] = ploadt_ro_aligned(from + 2);
1088 r_alias[2] = ploadt_ro_aligned(from + 4);
1089 r_alias[3] = ploadt_ro_aligned(from + 6);
1090 return r;
1091#endif
Sami Kamab733b8b2020-03-10 20:28:43 +00001092}
1093
1094template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001095EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet4h2 ploadt_ro<Packet4h2, Unaligned>(const Eigen::half* from) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001096 Packet4h2 r;
1097 half2* r_alias = reinterpret_cast<half2*>(&r);
1098 r_alias[0] = ploadt_ro_unaligned(from + 0);
1099 r_alias[1] = ploadt_ro_unaligned(from + 2);
1100 r_alias[2] = ploadt_ro_unaligned(from + 4);
1101 r_alias[3] = ploadt_ro_unaligned(from + 6);
1102 return r;
1103}
1104
1105template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001106EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pgather<Eigen::half, Packet4h2>(const Eigen::half* from, Index stride) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001107 Packet4h2 r;
1108 half2* p_alias = reinterpret_cast<half2*>(&r);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -07001109 p_alias[0] = __halves2half2(from[0 * stride], from[1 * stride]);
1110 p_alias[1] = __halves2half2(from[2 * stride], from[3 * stride]);
1111 p_alias[2] = __halves2half2(from[4 * stride], from[5 * stride]);
1112 p_alias[3] = __halves2half2(from[6 * stride], from[7 * stride]);
Sami Kamab733b8b2020-03-10 20:28:43 +00001113 return r;
1114}
1115
1116template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001117EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void pscatter<Eigen::half, Packet4h2>(Eigen::half* to, const Packet4h2& from,
1118 Index stride) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001119 const half2* from_alias = reinterpret_cast<const half2*>(&from);
1120 pscatter(to + stride * 0, from_alias[0], stride);
1121 pscatter(to + stride * 2, from_alias[1], stride);
1122 pscatter(to + stride * 4, from_alias[2], stride);
1123 pscatter(to + stride * 6, from_alias[3], stride);
1124}
1125
1126template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001127EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half pfirst<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001128 return pfirst(*(reinterpret_cast<const half2*>(&a)));
1129}
1130
1131template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001132EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pabs<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001133 Packet4h2 r;
1134 half2* p_alias = reinterpret_cast<half2*>(&r);
1135 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1136 p_alias[0] = pabs(a_alias[0]);
1137 p_alias[1] = pabs(a_alias[1]);
1138 p_alias[2] = pabs(a_alias[2]);
1139 p_alias[3] = pabs(a_alias[3]);
1140 return r;
1141}
1142
1143template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001144EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 ptrue<Packet4h2>(const Packet4h2& /*a*/) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001145 half true_half = half_impl::raw_uint16_to_half(0xffffu);
1146 return pset1<Packet4h2>(true_half);
1147}
1148
1149template <>
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001150EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pzero<Packet4h2>(const Packet4h2& /*a*/) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001151 half false_half = half_impl::raw_uint16_to_half(0x0000u);
1152 return pset1<Packet4h2>(false_half);
1153}
1154
Tobias Woodf38e16c2023-11-29 11:12:48 +00001155EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_double(double* d_row0, double* d_row1, double* d_row2,
1156 double* d_row3, double* d_row4, double* d_row5,
1157 double* d_row6, double* d_row7) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001158 double d_tmp;
1159 d_tmp = d_row0[1];
1160 d_row0[1] = d_row4[0];
1161 d_row4[0] = d_tmp;
1162
1163 d_tmp = d_row1[1];
1164 d_row1[1] = d_row5[0];
1165 d_row5[0] = d_tmp;
1166
1167 d_tmp = d_row2[1];
1168 d_row2[1] = d_row6[0];
1169 d_row6[0] = d_tmp;
1170
1171 d_tmp = d_row3[1];
1172 d_row3[1] = d_row7[0];
1173 d_row7[0] = d_tmp;
1174}
1175
Tobias Woodf38e16c2023-11-29 11:12:48 +00001176EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_half2(half2* f_row0, half2* f_row1, half2* f_row2,
1177 half2* f_row3) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001178 half2 f_tmp;
1179 f_tmp = f_row0[1];
1180 f_row0[1] = f_row2[0];
1181 f_row2[0] = f_tmp;
1182
1183 f_tmp = f_row1[1];
1184 f_row1[1] = f_row3[0];
1185 f_row3[0] = f_tmp;
1186}
1187
Tobias Woodf38e16c2023-11-29 11:12:48 +00001188EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose_half(half2& f0, half2& f1) {
Antonio Sanchezcc3573a2021-08-31 08:33:19 -07001189 __half a1 = __low2half(f0);
1190 __half a2 = __high2half(f0);
1191 __half b1 = __low2half(f1);
1192 __half b2 = __high2half(f1);
1193 f0 = __halves2half2(a1, b1);
1194 f1 = __halves2half2(a2, b2);
Sami Kamab733b8b2020-03-10 20:28:43 +00001195}
1196
Tobias Woodf38e16c2023-11-29 11:12:48 +00001197EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet4h2, 8>& kernel) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001198 double* d_row0 = reinterpret_cast<double*>(&kernel.packet[0]);
1199 double* d_row1 = reinterpret_cast<double*>(&kernel.packet[1]);
1200 double* d_row2 = reinterpret_cast<double*>(&kernel.packet[2]);
1201 double* d_row3 = reinterpret_cast<double*>(&kernel.packet[3]);
1202 double* d_row4 = reinterpret_cast<double*>(&kernel.packet[4]);
1203 double* d_row5 = reinterpret_cast<double*>(&kernel.packet[5]);
1204 double* d_row6 = reinterpret_cast<double*>(&kernel.packet[6]);
1205 double* d_row7 = reinterpret_cast<double*>(&kernel.packet[7]);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001206 ptranspose_double(d_row0, d_row1, d_row2, d_row3, d_row4, d_row5, d_row6, d_row7);
Sami Kamab733b8b2020-03-10 20:28:43 +00001207
1208 half2* f_row0 = reinterpret_cast<half2*>(d_row0);
1209 half2* f_row1 = reinterpret_cast<half2*>(d_row1);
1210 half2* f_row2 = reinterpret_cast<half2*>(d_row2);
1211 half2* f_row3 = reinterpret_cast<half2*>(d_row3);
1212 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1213 ptranspose_half(f_row0[0], f_row1[0]);
1214 ptranspose_half(f_row0[1], f_row1[1]);
1215 ptranspose_half(f_row2[0], f_row3[0]);
1216 ptranspose_half(f_row2[1], f_row3[1]);
1217
1218 f_row0 = reinterpret_cast<half2*>(d_row0 + 1);
1219 f_row1 = reinterpret_cast<half2*>(d_row1 + 1);
1220 f_row2 = reinterpret_cast<half2*>(d_row2 + 1);
1221 f_row3 = reinterpret_cast<half2*>(d_row3 + 1);
1222 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1223 ptranspose_half(f_row0[0], f_row1[0]);
1224 ptranspose_half(f_row0[1], f_row1[1]);
1225 ptranspose_half(f_row2[0], f_row3[0]);
1226 ptranspose_half(f_row2[1], f_row3[1]);
1227
1228 f_row0 = reinterpret_cast<half2*>(d_row4);
1229 f_row1 = reinterpret_cast<half2*>(d_row5);
1230 f_row2 = reinterpret_cast<half2*>(d_row6);
1231 f_row3 = reinterpret_cast<half2*>(d_row7);
1232 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1233 ptranspose_half(f_row0[0], f_row1[0]);
1234 ptranspose_half(f_row0[1], f_row1[1]);
1235 ptranspose_half(f_row2[0], f_row3[0]);
1236 ptranspose_half(f_row2[1], f_row3[1]);
1237
1238 f_row0 = reinterpret_cast<half2*>(d_row4 + 1);
1239 f_row1 = reinterpret_cast<half2*>(d_row5 + 1);
1240 f_row2 = reinterpret_cast<half2*>(d_row6 + 1);
1241 f_row3 = reinterpret_cast<half2*>(d_row7 + 1);
1242 ptranspose_half2(f_row0, f_row1, f_row2, f_row3);
1243 ptranspose_half(f_row0[0], f_row1[0]);
1244 ptranspose_half(f_row0[1], f_row1[1]);
1245 ptranspose_half(f_row2[0], f_row3[0]);
1246 ptranspose_half(f_row2[1], f_row3[1]);
Sami Kamab733b8b2020-03-10 20:28:43 +00001247}
1248
1249template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001250EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 plset<Packet4h2>(const Eigen::half& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001251#if defined(EIGEN_HIP_DEVICE_COMPILE)
1252
1253 Packet4h2 r;
1254 half2* p_alias = reinterpret_cast<half2*>(&r);
1255 p_alias[0] = __halves2half2(a, __hadd(a, __float2half(1.0f)));
Tobias Woodf38e16c2023-11-29 11:12:48 +00001256 p_alias[1] = __halves2half2(__hadd(a, __float2half(2.0f)), __hadd(a, __float2half(3.0f)));
1257 p_alias[2] = __halves2half2(__hadd(a, __float2half(4.0f)), __hadd(a, __float2half(5.0f)));
1258 p_alias[3] = __halves2half2(__hadd(a, __float2half(6.0f)), __hadd(a, __float2half(7.0f)));
Sami Kamab733b8b2020-03-10 20:28:43 +00001259 return r;
Antonio Sanchezdb5691f2021-02-19 08:52:31 -08001260#elif defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001261 Packet4h2 r;
1262 half2* r_alias = reinterpret_cast<half2*>(&r);
1263
1264 half2 b = pset1<half2>(a);
1265 half2 c;
Tobias Woodf38e16c2023-11-29 11:12:48 +00001266 half2 half_offset0 = __halves2half2(__float2half(0.0f), __float2half(2.0f));
1267 half2 half_offset1 = __halves2half2(__float2half(4.0f), __float2half(6.0f));
Sami Kamab733b8b2020-03-10 20:28:43 +00001268
1269 c = __hadd2(b, half_offset0);
1270 r_alias[0] = plset(__low2half(c));
1271 r_alias[1] = plset(__high2half(c));
1272
1273 c = __hadd2(b, half_offset1);
1274 r_alias[2] = plset(__low2half(c));
1275 r_alias[3] = plset(__high2half(c));
1276
1277 return r;
1278
1279#else
1280 float f = __half2float(a);
1281 Packet4h2 r;
1282 half2* p_alias = reinterpret_cast<half2*>(&r);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -07001283 p_alias[0] = __halves2half2(a, __float2half(f + 1.0f));
1284 p_alias[1] = __halves2half2(__float2half(f + 2.0f), __float2half(f + 3.0f));
1285 p_alias[2] = __halves2half2(__float2half(f + 4.0f), __float2half(f + 5.0f));
1286 p_alias[3] = __halves2half2(__float2half(f + 6.0f), __float2half(f + 7.0f));
Sami Kamab733b8b2020-03-10 20:28:43 +00001287 return r;
1288#endif
Sami Kamab733b8b2020-03-10 20:28:43 +00001289}
1290
1291template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001292EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pselect<Packet4h2>(const Packet4h2& mask, const Packet4h2& a,
1293 const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001294 Packet4h2 r;
1295 half2* r_alias = reinterpret_cast<half2*>(&r);
1296 const half2* mask_alias = reinterpret_cast<const half2*>(&mask);
1297 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1298 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1299 r_alias[0] = pselect(mask_alias[0], a_alias[0], b_alias[0]);
1300 r_alias[1] = pselect(mask_alias[1], a_alias[1], b_alias[1]);
1301 r_alias[2] = pselect(mask_alias[2], a_alias[2], b_alias[2]);
1302 r_alias[3] = pselect(mask_alias[3], a_alias[3], b_alias[3]);
1303 return r;
1304}
1305
1306template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001307EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pcmp_eq<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001308 Packet4h2 r;
1309 half2* r_alias = reinterpret_cast<half2*>(&r);
1310 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1311 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1312 r_alias[0] = pcmp_eq(a_alias[0], b_alias[0]);
1313 r_alias[1] = pcmp_eq(a_alias[1], b_alias[1]);
1314 r_alias[2] = pcmp_eq(a_alias[2], b_alias[2]);
1315 r_alias[3] = pcmp_eq(a_alias[3], b_alias[3]);
1316 return r;
1317}
1318
1319template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001320EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pcmp_lt<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -07001321 Packet4h2 r;
1322 half2* r_alias = reinterpret_cast<half2*>(&r);
1323 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1324 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1325 r_alias[0] = pcmp_lt(a_alias[0], b_alias[0]);
1326 r_alias[1] = pcmp_lt(a_alias[1], b_alias[1]);
1327 r_alias[2] = pcmp_lt(a_alias[2], b_alias[2]);
1328 r_alias[3] = pcmp_lt(a_alias[3], b_alias[3]);
1329 return r;
1330}
1331
1332template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001333EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pcmp_le<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Rasmus Munk Larsenf9dfda22022-09-07 14:10:02 -07001334 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] = pcmp_le(a_alias[0], b_alias[0]);
1339 r_alias[1] = pcmp_le(a_alias[1], b_alias[1]);
1340 r_alias[2] = pcmp_le(a_alias[2], b_alias[2]);
1341 r_alias[3] = pcmp_le(a_alias[3], b_alias[3]);
1342 return r;
1343}
1344
1345template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001346EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pand<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001347 Packet4h2 r;
1348 half2* r_alias = reinterpret_cast<half2*>(&r);
1349 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1350 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1351 r_alias[0] = pand(a_alias[0], b_alias[0]);
1352 r_alias[1] = pand(a_alias[1], b_alias[1]);
1353 r_alias[2] = pand(a_alias[2], b_alias[2]);
1354 r_alias[3] = pand(a_alias[3], b_alias[3]);
1355 return r;
1356}
1357
1358template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001359EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 por<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001360 Packet4h2 r;
1361 half2* r_alias = reinterpret_cast<half2*>(&r);
1362 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1363 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1364 r_alias[0] = por(a_alias[0], b_alias[0]);
1365 r_alias[1] = por(a_alias[1], b_alias[1]);
1366 r_alias[2] = por(a_alias[2], b_alias[2]);
1367 r_alias[3] = por(a_alias[3], b_alias[3]);
1368 return r;
1369}
1370
1371template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001372EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pxor<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001373 Packet4h2 r;
1374 half2* r_alias = reinterpret_cast<half2*>(&r);
1375 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1376 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1377 r_alias[0] = pxor(a_alias[0], b_alias[0]);
1378 r_alias[1] = pxor(a_alias[1], b_alias[1]);
1379 r_alias[2] = pxor(a_alias[2], b_alias[2]);
1380 r_alias[3] = pxor(a_alias[3], b_alias[3]);
1381 return r;
1382}
1383
1384template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001385EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pandnot<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001386 Packet4h2 r;
1387 half2* r_alias = reinterpret_cast<half2*>(&r);
1388 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1389 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1390 r_alias[0] = pandnot(a_alias[0], b_alias[0]);
1391 r_alias[1] = pandnot(a_alias[1], b_alias[1]);
1392 r_alias[2] = pandnot(a_alias[2], b_alias[2]);
1393 r_alias[3] = pandnot(a_alias[3], b_alias[3]);
1394 return r;
1395}
1396
1397template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001398EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 padd<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001399 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] = padd(a_alias[0], b_alias[0]);
1404 r_alias[1] = padd(a_alias[1], b_alias[1]);
1405 r_alias[2] = padd(a_alias[2], b_alias[2]);
1406 r_alias[3] = padd(a_alias[3], b_alias[3]);
1407 return r;
1408}
1409
1410template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001411EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psub<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001412 Packet4h2 r;
1413 half2* r_alias = reinterpret_cast<half2*>(&r);
1414 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1415 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1416 r_alias[0] = psub(a_alias[0], b_alias[0]);
1417 r_alias[1] = psub(a_alias[1], b_alias[1]);
1418 r_alias[2] = psub(a_alias[2], b_alias[2]);
1419 r_alias[3] = psub(a_alias[3], b_alias[3]);
1420 return r;
1421}
1422
1423template <>
1424EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pnegate(const Packet4h2& a) {
1425 Packet4h2 r;
1426 half2* r_alias = reinterpret_cast<half2*>(&r);
1427 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1428 r_alias[0] = pnegate(a_alias[0]);
1429 r_alias[1] = pnegate(a_alias[1]);
1430 r_alias[2] = pnegate(a_alias[2]);
1431 r_alias[3] = pnegate(a_alias[3]);
1432 return r;
1433}
1434
1435template <>
1436EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pconj(const Packet4h2& a) {
1437 return a;
1438}
1439
1440template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001441EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmul<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001442 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] = pmul(a_alias[0], b_alias[0]);
1447 r_alias[1] = pmul(a_alias[1], b_alias[1]);
1448 r_alias[2] = pmul(a_alias[2], b_alias[2]);
1449 r_alias[3] = pmul(a_alias[3], b_alias[3]);
1450 return r;
1451}
1452
1453template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001454EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmadd<Packet4h2>(const Packet4h2& a, const Packet4h2& b,
1455 const Packet4h2& c) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001456 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 const half2* c_alias = reinterpret_cast<const half2*>(&c);
1461 r_alias[0] = pmadd(a_alias[0], b_alias[0], c_alias[0]);
1462 r_alias[1] = pmadd(a_alias[1], b_alias[1], c_alias[1]);
1463 r_alias[2] = pmadd(a_alias[2], b_alias[2], c_alias[2]);
1464 r_alias[3] = pmadd(a_alias[3], b_alias[3], c_alias[3]);
1465 return r;
1466}
1467
1468template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001469EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pdiv<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001470 Packet4h2 r;
1471 half2* r_alias = reinterpret_cast<half2*>(&r);
1472 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1473 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1474 r_alias[0] = pdiv(a_alias[0], b_alias[0]);
1475 r_alias[1] = pdiv(a_alias[1], b_alias[1]);
1476 r_alias[2] = pdiv(a_alias[2], b_alias[2]);
1477 r_alias[3] = pdiv(a_alias[3], b_alias[3]);
1478 return r;
1479}
1480
1481template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001482EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmin<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001483 Packet4h2 r;
1484 half2* r_alias = reinterpret_cast<half2*>(&r);
1485 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1486 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1487 r_alias[0] = pmin(a_alias[0], b_alias[0]);
1488 r_alias[1] = pmin(a_alias[1], b_alias[1]);
1489 r_alias[2] = pmin(a_alias[2], b_alias[2]);
1490 r_alias[3] = pmin(a_alias[3], b_alias[3]);
1491 return r;
1492}
1493
1494template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001495EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pmax<Packet4h2>(const Packet4h2& a, const Packet4h2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001496 Packet4h2 r;
1497 half2* r_alias = reinterpret_cast<half2*>(&r);
1498 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1499 const half2* b_alias = reinterpret_cast<const half2*>(&b);
1500 r_alias[0] = pmax(a_alias[0], b_alias[0]);
1501 r_alias[1] = pmax(a_alias[1], b_alias[1]);
1502 r_alias[2] = pmax(a_alias[2], b_alias[2]);
1503 r_alias[3] = pmax(a_alias[3], b_alias[3]);
1504 return r;
1505}
1506
1507template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001508EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001509 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1510
Tobias Woodf38e16c2023-11-29 11:12:48 +00001511 return predux(a_alias[0]) + predux(a_alias[1]) + predux(a_alias[2]) + predux(a_alias[3]);
Sami Kamab733b8b2020-03-10 20:28:43 +00001512}
1513
1514template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001515EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_max<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001516 const half2* a_alias = reinterpret_cast<const half2*>(&a);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001517 half2 m0 = __halves2half2(predux_max(a_alias[0]), predux_max(a_alias[1]));
1518 half2 m1 = __halves2half2(predux_max(a_alias[2]), predux_max(a_alias[3]));
1519 __half first = predux_max(m0);
Sami Kamab733b8b2020-03-10 20:28:43 +00001520 __half second = predux_max(m1);
Antonio Sanchezdb5691f2021-02-19 08:52:31 -08001521#if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001522 return (__hgt(first, second) ? first : second);
1523#else
Tobias Woodf38e16c2023-11-29 11:12:48 +00001524 float ffirst = __half2float(first);
Sami Kamab733b8b2020-03-10 20:28:43 +00001525 float fsecond = __half2float(second);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001526 return (ffirst > fsecond) ? first : second;
Sami Kamab733b8b2020-03-10 20:28:43 +00001527#endif
1528}
1529
1530template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001531EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_min<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001532 const half2* a_alias = reinterpret_cast<const half2*>(&a);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001533 half2 m0 = __halves2half2(predux_min(a_alias[0]), predux_min(a_alias[1]));
1534 half2 m1 = __halves2half2(predux_min(a_alias[2]), predux_min(a_alias[3]));
1535 __half first = predux_min(m0);
Sami Kamab733b8b2020-03-10 20:28:43 +00001536 __half second = predux_min(m1);
Antonio Sanchezdb5691f2021-02-19 08:52:31 -08001537#if defined(EIGEN_CUDA_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001538 return (__hlt(first, second) ? first : second);
1539#else
Tobias Woodf38e16c2023-11-29 11:12:48 +00001540 float ffirst = __half2float(first);
Sami Kamab733b8b2020-03-10 20:28:43 +00001541 float fsecond = __half2float(second);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001542 return (ffirst < fsecond) ? first : second;
Sami Kamab733b8b2020-03-10 20:28:43 +00001543#endif
1544}
1545
1546// likely overflow/underflow
1547template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001548EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001549 const half2* a_alias = reinterpret_cast<const half2*>(&a);
Tobias Woodf38e16c2023-11-29 11:12:48 +00001550 return predux_mul(pmul(pmul(a_alias[0], a_alias[1]), pmul(a_alias[2], a_alias[3])));
Sami Kamab733b8b2020-03-10 20:28:43 +00001551}
1552
1553template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001554EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 plog1p<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001555 Packet4h2 r;
1556 half2* r_alias = reinterpret_cast<half2*>(&r);
1557 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1558 r_alias[0] = plog1p(a_alias[0]);
1559 r_alias[1] = plog1p(a_alias[1]);
1560 r_alias[2] = plog1p(a_alias[2]);
1561 r_alias[3] = plog1p(a_alias[3]);
1562 return r;
1563}
1564
1565template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001566EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pexpm1<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001567 Packet4h2 r;
1568 half2* r_alias = reinterpret_cast<half2*>(&r);
1569 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1570 r_alias[0] = pexpm1(a_alias[0]);
1571 r_alias[1] = pexpm1(a_alias[1]);
1572 r_alias[2] = pexpm1(a_alias[2]);
1573 r_alias[3] = pexpm1(a_alias[3]);
1574 return r;
1575}
1576
1577template <>
1578EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 plog<Packet4h2>(const Packet4h2& a) {
1579 Packet4h2 r;
1580 half2* r_alias = reinterpret_cast<half2*>(&r);
1581 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1582 r_alias[0] = plog(a_alias[0]);
1583 r_alias[1] = plog(a_alias[1]);
1584 r_alias[2] = plog(a_alias[2]);
1585 r_alias[3] = plog(a_alias[3]);
1586 return r;
1587}
1588
1589template <>
1590EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 pexp<Packet4h2>(const Packet4h2& a) {
1591 Packet4h2 r;
1592 half2* r_alias = reinterpret_cast<half2*>(&r);
1593 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1594 r_alias[0] = pexp(a_alias[0]);
1595 r_alias[1] = pexp(a_alias[1]);
1596 r_alias[2] = pexp(a_alias[2]);
1597 r_alias[3] = pexp(a_alias[3]);
1598 return r;
1599}
1600
1601template <>
1602EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 psqrt<Packet4h2>(const Packet4h2& a) {
1603 Packet4h2 r;
1604 half2* r_alias = reinterpret_cast<half2*>(&r);
1605 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1606 r_alias[0] = psqrt(a_alias[0]);
1607 r_alias[1] = psqrt(a_alias[1]);
1608 r_alias[2] = psqrt(a_alias[2]);
1609 r_alias[3] = psqrt(a_alias[3]);
1610 return r;
1611}
1612
1613template <>
Tobias Woodf38e16c2023-11-29 11:12:48 +00001614EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet4h2 prsqrt<Packet4h2>(const Packet4h2& a) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001615 Packet4h2 r;
1616 half2* r_alias = reinterpret_cast<half2*>(&r);
1617 const half2* a_alias = reinterpret_cast<const half2*>(&a);
1618 r_alias[0] = prsqrt(a_alias[0]);
1619 r_alias[1] = prsqrt(a_alias[1]);
1620 r_alias[2] = prsqrt(a_alias[2]);
1621 r_alias[3] = prsqrt(a_alias[3]);
1622 return r;
1623}
1624
1625// The following specialized padd, pmul, pdiv, pmin, pmax, pset1 are needed for
1626// the implementation of GPU half reduction.
Tobias Woodf38e16c2023-11-29 11:12:48 +00001627template <>
1628EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 padd<half2>(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001629#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001630 return __hadd2(a, b);
1631#else
1632 float a1 = __low2float(a);
1633 float a2 = __high2float(a);
1634 float b1 = __low2float(b);
1635 float b2 = __high2float(b);
1636 float r1 = a1 + b1;
1637 float r2 = a2 + b2;
1638 return __floats2half2_rn(r1, r2);
1639#endif
Sami Kamab733b8b2020-03-10 20:28:43 +00001640}
1641
Tobias Woodf38e16c2023-11-29 11:12:48 +00001642template <>
1643EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmul<half2>(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001644#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001645 return __hmul2(a, b);
1646#else
1647 float a1 = __low2float(a);
1648 float a2 = __high2float(a);
1649 float b1 = __low2float(b);
1650 float b2 = __high2float(b);
1651 float r1 = a1 * b1;
1652 float r2 = a2 * b2;
1653 return __floats2half2_rn(r1, r2);
1654#endif
Sami Kamab733b8b2020-03-10 20:28:43 +00001655}
1656
Tobias Woodf38e16c2023-11-29 11:12:48 +00001657template <>
1658EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pdiv<half2>(const half2& a, const half2& b) {
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001659#if defined(EIGEN_GPU_HAS_FP16_ARITHMETIC)
Sami Kamab733b8b2020-03-10 20:28:43 +00001660 return __h2div(a, b);
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001661#else
Sami Kamab733b8b2020-03-10 20:28:43 +00001662 float a1 = __low2float(a);
1663 float a2 = __high2float(a);
1664 float b1 = __low2float(b);
1665 float b2 = __high2float(b);
1666 float r1 = a1 / b1;
1667 float r2 = a2 / b2;
1668 return __floats2half2_rn(r1, r2);
Sami Kamab733b8b2020-03-10 20:28:43 +00001669#endif
1670}
1671
Tobias Woodf38e16c2023-11-29 11:12:48 +00001672template <>
1673EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmin<half2>(const half2& a, const half2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001674 float a1 = __low2float(a);
1675 float a2 = __high2float(a);
1676 float b1 = __low2float(b);
1677 float b2 = __high2float(b);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -07001678 __half r1 = a1 < b1 ? __low2half(a) : __low2half(b);
1679 __half r2 = a2 < b2 ? __high2half(a) : __high2half(b);
1680 return __halves2half2(r1, r2);
Sami Kamab733b8b2020-03-10 20:28:43 +00001681}
1682
Tobias Woodf38e16c2023-11-29 11:12:48 +00001683template <>
1684EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE half2 pmax<half2>(const half2& a, const half2& b) {
Sami Kamab733b8b2020-03-10 20:28:43 +00001685 float a1 = __low2float(a);
1686 float a2 = __high2float(a);
1687 float b1 = __low2float(b);
1688 float b2 = __high2float(b);
Antonio Sanchezcc3573a2021-08-31 08:33:19 -07001689 __half r1 = a1 > b1 ? __low2half(a) : __low2half(b);
1690 __half r2 = a2 > b2 ? __high2half(a) : __high2half(b);
1691 return __halves2half2(r1, r2);
Sami Kamab733b8b2020-03-10 20:28:43 +00001692}
1693
Tobias Woodf38e16c2023-11-29 11:12:48 +00001694#endif // (defined(EIGEN_HAS_CUDA_FP16) || defined(EIGEN_HAS_HIP_FP16)) && defined(EIGEN_GPU_COMPILE_PHASE)
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001695
1696#undef EIGEN_GPU_HAS_LDG
Antonio Sanchezdb5691f2021-02-19 08:52:31 -08001697#undef EIGEN_CUDA_HAS_FP16_ARITHMETIC
Antonio Sanchez8cfe0db2020-12-07 19:11:07 -08001698#undef EIGEN_GPU_HAS_FP16_ARITHMETIC
Rasmus Munk Larsenb021cde2019-08-27 11:30:31 -07001699
Tobias Woodf38e16c2023-11-29 11:12:48 +00001700} // end namespace internal
Benoit Steiner95a430a2014-10-03 19:45:19 -07001701
Tobias Woodf38e16c2023-11-29 11:12:48 +00001702} // end namespace Eigen
Benoit Steiner95a430a2014-10-03 19:45:19 -07001703
Tobias Woodf38e16c2023-11-29 11:12:48 +00001704#endif // EIGEN_PACKET_MATH_GPU_H