Eigen  5.0.1
 
Loading...
Searching...
No Matches
PacketMathFP16.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2025 Kseniya Zaytseva <kseniya.zaytseva@syntacore.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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_PACKET_MATH_FP16_RVV10_H
12#define EIGEN_PACKET_MATH_FP16_RVV10_H
13
14// IWYU pragma: private
15#include "../../InternalHeaderCheck.h"
16
17namespace Eigen {
18namespace internal {
19
20typedef eigen_packet_wrapper<vfloat16m1_t __attribute__((riscv_rvv_vector_bits(EIGEN_RISCV64_RVV_VL))), 24> Packet1Xh;
21typedef eigen_packet_wrapper<vfloat16m2_t __attribute__((riscv_rvv_vector_bits(EIGEN_RISCV64_RVV_VL * 2))), 25>
22 Packet2Xh;
23
24template <>
25struct rvv_half_packet<Packet2Xh> {
26 typedef Packet1Xh type;
27};
28
29template <>
30struct unpacket_traits<Packet1Xh> : rvv_default_unpacket_traits<Eigen::half, Packet1Xh, 1> {
31 typedef Packet1Xs integer_packet;
32 typedef PacketMask16 packet_mask;
33};
34
35template <>
36struct unpacket_traits<Packet2Xh> : rvv_default_unpacket_traits<Eigen::half, Packet2Xh, 2> {
37 typedef Packet2Xs integer_packet;
38 typedef PacketMask8 packet_mask;
39};
40
41#if EIGEN_RISCV64_DEFAULT_LMUL == 1
42typedef Packet1Xh PacketXh;
43#else
44typedef Packet2Xh PacketXh;
45#endif
46
47template <>
48struct packet_traits<Eigen::half> : rvv_default_packet_traits<Eigen::half, PacketXh> {
49 enum {
50 HasAdd = 1,
51 HasSub = 1,
52 HasShift = 1,
53 HasMul = 1,
54 HasNegate = 1,
55 HasAbs = 1,
56 HasArg = 0,
57 HasAbs2 = 1,
58 HasMin = 1,
59 HasMax = 1,
60 HasConj = 1,
61 HasSetLinear = 0,
62 HasBlend = 0,
63 HasReduxp = 0,
64 HasSign = 0,
65
66 HasCmp = 1,
67 HasDiv = 1,
68 HasRound = 1,
69
70 HasSin = EIGEN_FAST_MATH,
71 HasCos = EIGEN_FAST_MATH,
72 HasLog = 0,
73 HasExp = 0,
74 HasSqrt = 1,
75 HasTanh = EIGEN_FAST_MATH,
76 HasErf = 0
77 };
78};
79
80/********************************* Packet1Xh ************************************/
81
82EIGEN_STRONG_INLINE Packet1Xh __riscv_vreinterpret_v_u32m1_f16m1(const Packet1Xu& a) {
83 return __riscv_vreinterpret_v_u16m1_f16m1(__riscv_vreinterpret_v_u32m1_u16m1(a));
84}
85
86template <>
87EIGEN_STRONG_INLINE Packet1Xh ptrue<Packet1Xh>(const Packet1Xh& /*a*/) {
88 Packet1Xh r = __riscv_vreinterpret_f16m1(__riscv_vmv_v_x_u16m1(0xffffu, unpacket_traits<Packet1Xh>::size));
89 EIGEN_FAST_MATH_CONSTANT_BARRIER(r);
90 return r;
91}
92
93template <>
94EIGEN_STRONG_INLINE Packet1Xh pzero<Packet1Xh>(const Packet1Xh& /*a*/) {
95 return __riscv_vfmv_v_f_f16m1(static_cast<_Float16>(0.0), unpacket_traits<Packet1Xh>::size);
96}
97
98template <>
99EIGEN_STRONG_INLINE Packet1Xh pabs(const Packet1Xh& a) {
100 return __riscv_vfabs_v_f16m1(a, unpacket_traits<Packet1Xh>::size);
101}
102
103template <>
104EIGEN_STRONG_INLINE Packet1Xh pabsdiff(const Packet1Xh& a, const Packet1Xh& b) {
105 return __riscv_vfabs_v_f16m1(__riscv_vfsub_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size),
106 unpacket_traits<Packet1Xh>::size);
107}
108
109template <>
110EIGEN_STRONG_INLINE Packet1Xh pset1<Packet1Xh>(const Eigen::half& from) {
111 return __riscv_vfmv_v_f_f16m1(numext::bit_cast<_Float16>(from), unpacket_traits<Packet1Xh>::size);
112}
113
114template <>
115EIGEN_STRONG_INLINE Packet1Xh pset1frombits<Packet1Xh>(numext::uint16_t from) {
116 return __riscv_vreinterpret_f16m1(__riscv_vmv_v_x_u16m1(from, unpacket_traits<Packet1Xh>::size));
117}
118
119template <>
120EIGEN_STRONG_INLINE Packet1Xh plset<Packet1Xh>(const Eigen::half& a) {
121 Packet1Xh idx = __riscv_vfcvt_f_x_v_f16m1(
122 __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vid_v_u16m1(unpacket_traits<Packet1Xs>::size)),
123 unpacket_traits<Packet1Xh>::size);
124 return __riscv_vfadd_vf_f16m1(idx, numext::bit_cast<_Float16>(a), unpacket_traits<Packet1Xh>::size);
125}
126
127template <>
128EIGEN_STRONG_INLINE void pbroadcast4<Packet1Xh>(const Eigen::half* a, Packet1Xh& a0, Packet1Xh& a1, Packet1Xh& a2,
129 Packet1Xh& a3) {
130 vfloat16m1_t aa = __riscv_vle16_v_f16m1(reinterpret_cast<const _Float16*>(a), 4);
131 a0 = __riscv_vrgather_vx_f16m1(aa, 0, unpacket_traits<Packet1Xh>::size);
132 a1 = __riscv_vrgather_vx_f16m1(aa, 1, unpacket_traits<Packet1Xh>::size);
133 a2 = __riscv_vrgather_vx_f16m1(aa, 2, unpacket_traits<Packet1Xh>::size);
134 a3 = __riscv_vrgather_vx_f16m1(aa, 3, unpacket_traits<Packet1Xh>::size);
135}
136
137template <>
138EIGEN_STRONG_INLINE Packet1Xh padd<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
139 return __riscv_vfadd_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
140}
141
142template <>
143EIGEN_STRONG_INLINE Packet1Xh psub<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
144 return __riscv_vfsub_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
145}
146
147template <>
148EIGEN_STRONG_INLINE Packet1Xh pnegate(const Packet1Xh& a) {
149 return __riscv_vfneg_v_f16m1(a, unpacket_traits<Packet1Xh>::size);
150}
151
152template <>
153EIGEN_STRONG_INLINE Packet1Xh psignbit(const Packet1Xh& a) {
154 return __riscv_vreinterpret_v_i16m1_f16m1(
155 __riscv_vsra_vx_i16m1(__riscv_vreinterpret_v_f16m1_i16m1(a), 15, unpacket_traits<Packet1Xs>::size));
156}
157
158template <>
159EIGEN_STRONG_INLINE Packet1Xh pmul<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
160 return __riscv_vfmul_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
161}
162
163template <>
164EIGEN_STRONG_INLINE Packet1Xh pdiv<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
165 return __riscv_vfdiv_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
166}
167
168template <>
169EIGEN_STRONG_INLINE Packet1Xh pmadd(const Packet1Xh& a, const Packet1Xh& b, const Packet1Xh& c) {
170 return __riscv_vfmadd_vv_f16m1(a, b, c, unpacket_traits<Packet1Xh>::size);
171}
172
173template <>
174EIGEN_STRONG_INLINE Packet1Xh pmsub(const Packet1Xh& a, const Packet1Xh& b, const Packet1Xh& c) {
175 return __riscv_vfmsub_vv_f16m1(a, b, c, unpacket_traits<Packet1Xh>::size);
176}
177
178template <>
179EIGEN_STRONG_INLINE Packet1Xh pnmadd(const Packet1Xh& a, const Packet1Xh& b, const Packet1Xh& c) {
180 return __riscv_vfnmsub_vv_f16m1(a, b, c, unpacket_traits<Packet1Xh>::size);
181}
182
183template <>
184EIGEN_STRONG_INLINE Packet1Xh pnmsub(const Packet1Xh& a, const Packet1Xh& b, const Packet1Xh& c) {
185 return __riscv_vfnmadd_vv_f16m1(a, b, c, unpacket_traits<Packet1Xh>::size);
186}
187
188template <>
189struct pminmax_propagates_nan<Packet1Xh> : bool_constant<true> {};
190
191template <>
192EIGEN_STRONG_INLINE Packet1Xh pmin<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
193 const Eigen::half nan = (std::numeric_limits<Eigen::half>::quiet_NaN)();
194 Packet1Xh nans = __riscv_vfmv_v_f_f16m1(numext::bit_cast<_Float16>(nan), unpacket_traits<Packet1Xh>::size);
195 PacketMask16 mask = __riscv_vmfeq_vv_f16m1_b16(a, a, unpacket_traits<Packet1Xh>::size);
196 PacketMask16 mask2 = __riscv_vmfeq_vv_f16m1_b16(b, b, unpacket_traits<Packet1Xh>::size);
197 mask = __riscv_vmand_mm_b16(mask, mask2, unpacket_traits<Packet1Xh>::size);
198
199 return __riscv_vfmin_vv_f16m1_tumu(mask, nans, a, b, unpacket_traits<Packet1Xh>::size);
200}
201
202template <>
203EIGEN_STRONG_INLINE Packet1Xh pmin<PropagateNumbers, Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
204 return __riscv_vfmin_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
205}
206
207template <>
208EIGEN_STRONG_INLINE Packet1Xh pmax<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
209 const Eigen::half nan = (std::numeric_limits<Eigen::half>::quiet_NaN)();
210 Packet1Xh nans = __riscv_vfmv_v_f_f16m1(numext::bit_cast<_Float16>(nan), unpacket_traits<Packet1Xh>::size);
211 PacketMask16 mask = __riscv_vmfeq_vv_f16m1_b16(a, a, unpacket_traits<Packet1Xh>::size);
212 PacketMask16 mask2 = __riscv_vmfeq_vv_f16m1_b16(b, b, unpacket_traits<Packet1Xh>::size);
213 mask = __riscv_vmand_mm_b16(mask, mask2, unpacket_traits<Packet1Xh>::size);
214
215 return __riscv_vfmax_vv_f16m1_tumu(mask, nans, a, b, unpacket_traits<Packet1Xh>::size);
216}
217
218template <>
219EIGEN_STRONG_INLINE Packet1Xh pmax<PropagateNumbers, Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
220 return __riscv_vfmax_vv_f16m1(a, b, unpacket_traits<Packet1Xh>::size);
221}
222
223template <>
224EIGEN_STRONG_INLINE Packet1Xh pcmp_le<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
225 PacketMask16 mask = __riscv_vmfle_vv_f16m1_b16(a, b, unpacket_traits<Packet1Xh>::size);
226 return __riscv_vmerge_vvm_f16m1(pzero<Packet1Xh>(a), ptrue<Packet1Xh>(a), mask, unpacket_traits<Packet1Xh>::size);
227}
228
229template <>
230EIGEN_STRONG_INLINE Packet1Xh pcmp_lt<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
231 PacketMask16 mask = __riscv_vmflt_vv_f16m1_b16(a, b, unpacket_traits<Packet1Xh>::size);
232 return __riscv_vmerge_vvm_f16m1(pzero<Packet1Xh>(a), ptrue<Packet1Xh>(a), mask, unpacket_traits<Packet1Xh>::size);
233}
234
235template <>
236EIGEN_STRONG_INLINE Packet1Xh pcmp_eq<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
237 PacketMask16 mask = __riscv_vmfeq_vv_f16m1_b16(a, b, unpacket_traits<Packet1Xh>::size);
238 return __riscv_vmerge_vvm_f16m1(pzero<Packet1Xh>(a), ptrue<Packet1Xh>(a), mask, unpacket_traits<Packet1Xh>::size);
239}
240
241template <>
242EIGEN_STRONG_INLINE Packet1Xh pcmp_lt_or_nan<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
243 PacketMask16 mask = __riscv_vmfge_vv_f16m1_b16(a, b, unpacket_traits<Packet1Xh>::size);
244 return __riscv_vfmerge_vfm_f16m1(ptrue<Packet1Xh>(a), static_cast<_Float16>(0.0), mask,
245 unpacket_traits<Packet1Xh>::size);
246}
247
248EIGEN_STRONG_INLINE Packet1Xh pselect(const PacketMask16& mask, const Packet1Xh& a, const Packet1Xh& b) {
249 return __riscv_vmerge_vvm_f16m1(b, a, mask, unpacket_traits<Packet1Xh>::size);
250}
251
252EIGEN_STRONG_INLINE Packet1Xh pselect(const Packet1Xh& mask, const Packet1Xh& a, const Packet1Xh& b) {
253 PacketMask16 mask2 =
254 __riscv_vmsne_vx_i16m1_b16(__riscv_vreinterpret_v_f16m1_i16m1(mask), 0, unpacket_traits<Packet1Xh>::size);
255 return __riscv_vreinterpret_v_i16m1_f16m1(__riscv_vmerge_vvm_i16m1(__riscv_vreinterpret_v_f16m1_i16m1(b),
256 __riscv_vreinterpret_v_f16m1_i16m1(a), mask2,
257 unpacket_traits<Packet1Xh>::size));
258}
259
260// Logical Operations are not supported for half, so reinterpret casts
261template <>
262EIGEN_STRONG_INLINE Packet1Xh pand<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
263 return __riscv_vreinterpret_v_u16m1_f16m1(__riscv_vand_vv_u16m1(
264 __riscv_vreinterpret_v_f16m1_u16m1(a), __riscv_vreinterpret_v_f16m1_u16m1(b), unpacket_traits<Packet1Xh>::size));
265}
266
267template <>
268EIGEN_STRONG_INLINE Packet1Xh por<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
269 return __riscv_vreinterpret_v_u16m1_f16m1(__riscv_vor_vv_u16m1(
270 __riscv_vreinterpret_v_f16m1_u16m1(a), __riscv_vreinterpret_v_f16m1_u16m1(b), unpacket_traits<Packet1Xh>::size));
271}
272
273template <>
274EIGEN_STRONG_INLINE Packet1Xh pxor<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
275 return __riscv_vreinterpret_v_u16m1_f16m1(__riscv_vxor_vv_u16m1(
276 __riscv_vreinterpret_v_f16m1_u16m1(a), __riscv_vreinterpret_v_f16m1_u16m1(b), unpacket_traits<Packet1Xh>::size));
277}
278
279template <>
280EIGEN_STRONG_INLINE Packet1Xh pnot<Packet1Xh>(const Packet1Xh& a) {
281 return __riscv_vreinterpret_v_u16m1_f16m1(
282 __riscv_vnot_v_u16m1(__riscv_vreinterpret_v_f16m1_u16m1(a), unpacket_traits<Packet1Xh>::size));
283}
284
285template <>
286EIGEN_STRONG_INLINE Packet1Xh pandnot<Packet1Xh>(const Packet1Xh& a, const Packet1Xh& b) {
287 return __riscv_vreinterpret_v_i16m1_f16m1(
288 pandnot<Packet1Xs>(__riscv_vreinterpret_v_f16m1_i16m1(a), __riscv_vreinterpret_v_f16m1_i16m1(b)));
289}
290
291template <>
292EIGEN_STRONG_INLINE Packet1Xh pload<Packet1Xh>(const Eigen::half* from) {
293 EIGEN_DEBUG_ALIGNED_LOAD return __riscv_vle16_v_f16m1(reinterpret_cast<const _Float16*>(from),
294 unpacket_traits<Packet1Xh>::size);
295}
296
297template <>
298EIGEN_STRONG_INLINE Packet1Xh ploadu<Packet1Xh>(const Eigen::half* from) {
299 EIGEN_DEBUG_UNALIGNED_LOAD return __riscv_vle16_v_f16m1(reinterpret_cast<const _Float16*>(from),
300 unpacket_traits<Packet1Xh>::size);
301}
302
303template <>
304EIGEN_STRONG_INLINE Packet1Xh ploaddup<Packet1Xh>(const Eigen::half* from) {
305 return __riscv_vreinterpret_v_i16m1_f16m1(ploaddup<Packet1Xs>(reinterpret_cast<const numext::int16_t*>(from)));
306}
307
308template <>
309EIGEN_STRONG_INLINE Packet1Xh ploadquad<Packet1Xh>(const Eigen::half* from) {
310 return __riscv_vreinterpret_v_i16m1_f16m1(ploadquad<Packet1Xs>(reinterpret_cast<const numext::int16_t*>(from)));
311}
312
313template <>
314EIGEN_STRONG_INLINE void pstore<Eigen::half>(Eigen::half* to, const Packet1Xh& from) {
315 EIGEN_DEBUG_ALIGNED_STORE __riscv_vse16_v_f16m1(reinterpret_cast<_Float16*>(to), from,
316 unpacket_traits<Packet1Xh>::size);
317}
318
319template <>
320EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(Eigen::half* to, const Packet1Xh& from) {
321 EIGEN_DEBUG_UNALIGNED_STORE __riscv_vse16_v_f16m1(reinterpret_cast<_Float16*>(to), from,
322 unpacket_traits<Packet1Xh>::size);
323}
324
325template <>
326EIGEN_DEVICE_FUNC inline Packet1Xh pgather<Eigen::half, Packet1Xh>(const Eigen::half* from, Index stride) {
327 return __riscv_vlse16_v_f16m1(reinterpret_cast<const _Float16*>(from), stride * sizeof(Eigen::half),
328 unpacket_traits<Packet1Xh>::size);
329}
330
331template <>
332EIGEN_DEVICE_FUNC inline void pscatter<Eigen::half, Packet1Xh>(Eigen::half* to, const Packet1Xh& from, Index stride) {
333 __riscv_vsse16(reinterpret_cast<_Float16*>(to), stride * sizeof(Eigen::half), from, unpacket_traits<Packet1Xh>::size);
334}
335
336template <>
337EIGEN_STRONG_INLINE Eigen::half pfirst<Packet1Xh>(const Packet1Xh& a) {
338 return static_cast<Eigen::half>(__riscv_vfmv_f_s_f16m1_f16(a));
339}
340
341template <>
342EIGEN_STRONG_INLINE Packet1Xh psqrt(const Packet1Xh& a) {
343 return __riscv_vfsqrt_v_f16m1(a, unpacket_traits<Packet1Xh>::size);
344}
345
346template <>
347EIGEN_STRONG_INLINE Packet1Xh print<Packet1Xh>(const Packet1Xh& a) {
348 const Packet1Xh limit = pset1<Packet1Xh>(static_cast<Eigen::half>(1 << 10));
349 const Packet1Xh abs_a = pabs(a);
350
351 PacketMask16 mask = __riscv_vmfne_vv_f16m1_b16(a, a, unpacket_traits<Packet1Xh>::size);
352 const Packet1Xh x = __riscv_vfadd_vv_f16m1_tumu(mask, a, a, a, unpacket_traits<Packet1Xh>::size);
353 const Packet1Xh new_x = __riscv_vfcvt_f_x_v_f16m1(__riscv_vfcvt_x_f_v_i16m1(a, unpacket_traits<Packet1Xh>::size),
354 unpacket_traits<Packet1Xh>::size);
355
356 mask = __riscv_vmflt_vv_f16m1_b16(abs_a, limit, unpacket_traits<Packet1Xh>::size);
357 Packet1Xh signed_x = __riscv_vfsgnj_vv_f16m1(new_x, x, unpacket_traits<Packet1Xh>::size);
358 return __riscv_vmerge_vvm_f16m1(x, signed_x, mask, unpacket_traits<Packet1Xh>::size);
359}
360
361template <>
362EIGEN_STRONG_INLINE Packet1Xh pfloor<Packet1Xh>(const Packet1Xh& a) {
363 Packet1Xh tmp = print<Packet1Xh>(a);
364 // If greater, subtract one.
365 PacketMask16 mask = __riscv_vmflt_vv_f16m1_b16(a, tmp, unpacket_traits<Packet1Xh>::size);
366 return __riscv_vfsub_vf_f16m1_tumu(mask, tmp, tmp, static_cast<_Float16>(1.0), unpacket_traits<Packet1Xh>::size);
367}
368
369template <>
370EIGEN_STRONG_INLINE Packet1Xh preverse(const Packet1Xh& a) {
371 Packet1Xsu idx = __riscv_vrsub_vx_u16m1(__riscv_vid_v_u16m1(unpacket_traits<Packet1Xh>::size),
372 unpacket_traits<Packet1Xh>::size - 1, unpacket_traits<Packet1Xh>::size);
373 return __riscv_vrgather_vv_f16m1(a, idx, unpacket_traits<Packet1Xh>::size);
374}
375
376template <>
377EIGEN_STRONG_INLINE Eigen::half predux<Packet1Xh>(const Packet1Xh& a) {
378 return static_cast<Eigen::half>(__riscv_vfmv_f(__riscv_vfredusum_vs_f16m1_f16m1(
379 a, __riscv_vfmv_v_f_f16m1(static_cast<_Float16>(0.0), unpacket_traits<Packet1Xh>::size),
380 unpacket_traits<Packet1Xh>::size)));
381}
382
383template <>
384EIGEN_STRONG_INLINE bool predux_any(const Packet1Xh& a) {
385 const PacketMask16 mask =
386 __riscv_vmsne_vx_u16m1_b16(__riscv_vreinterpret_v_f16m1_u16m1(a), 0, unpacket_traits<Packet1Xh>::size);
387 return __riscv_vcpop_m_b16(mask, unpacket_traits<Packet1Xh>::size) != 0;
388}
389
390template <>
391EIGEN_STRONG_INLINE bool predux_all(const Packet1Xh& a) {
392 const PacketMask16 mask = __riscv_vmfeq_vf_f16m1_b16(a, static_cast<_Float16>(0.0), unpacket_traits<Packet1Xh>::size);
393 return __riscv_vcpop_m_b16(mask, unpacket_traits<Packet1Xh>::size) == 0;
394}
395
396template <>
397EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet1Xh>(const Packet1Xh& a) {
398 // Multiply the vector by its reverse
399 Packet1Xh prod = __riscv_vfmul_vv_f16m1(preverse(a), a, unpacket_traits<Packet1Xh>::size);
400 Packet1Xh half_prod;
401
402 EIGEN_IF_CONSTEXPR (EIGEN_RISCV64_RVV_VL >= 1024) {
403 half_prod = __riscv_vslidedown_vx_f16m1(prod, 16, unpacket_traits<Packet1Xh>::size);
404 prod = __riscv_vfmul_vv_f16m1(prod, half_prod, unpacket_traits<Packet1Xh>::size);
405 }
406 EIGEN_IF_CONSTEXPR (EIGEN_RISCV64_RVV_VL >= 512) {
407 half_prod = __riscv_vslidedown_vx_f16m1(prod, 8, unpacket_traits<Packet1Xh>::size);
408 prod = __riscv_vfmul_vv_f16m1(prod, half_prod, unpacket_traits<Packet1Xh>::size);
409 }
410 EIGEN_IF_CONSTEXPR (EIGEN_RISCV64_RVV_VL >= 256) {
411 half_prod = __riscv_vslidedown_vx_f16m1(prod, 4, unpacket_traits<Packet1Xh>::size);
412 prod = __riscv_vfmul_vv_f16m1(prod, half_prod, unpacket_traits<Packet1Xh>::size);
413 }
414 // Last reduction
415 half_prod = __riscv_vslidedown_vx_f16m1(prod, 2, unpacket_traits<Packet1Xh>::size);
416 prod = __riscv_vfmul_vv_f16m1(prod, half_prod, unpacket_traits<Packet1Xh>::size);
417
418 half_prod = __riscv_vslidedown_vx_f16m1(prod, 1, unpacket_traits<Packet1Xh>::size);
419 prod = __riscv_vfmul_vv_f16m1(prod, half_prod, unpacket_traits<Packet1Xh>::size);
420
421 // The reduction is done to the first element.
422 return pfirst(prod);
423}
424
425// Reusing the first lane is exact for an idempotent reduction and avoids a NaN seed that becomes poison under
426// finite fast-math.
427template <>
428EIGEN_STRONG_INLINE Eigen::half predux_min<Packet1Xh>(const Packet1Xh& a) {
429 return static_cast<Eigen::half>(
430 __riscv_vfmv_f(__riscv_vfredmin_vs_f16m1_f16m1(a, a, unpacket_traits<Packet1Xh>::size)));
431}
432
433template <>
434EIGEN_STRONG_INLINE Eigen::half predux_max<Packet1Xh>(const Packet1Xh& a) {
435 return static_cast<Eigen::half>(
436 __riscv_vfmv_f(__riscv_vfredmax_vs_f16m1_f16m1(a, a, unpacket_traits<Packet1Xh>::size)));
437}
438
439template <int N>
440EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet1Xh, N>& kernel) {
441 Eigen::half buffer[unpacket_traits<Packet1Xh>::size * N];
442 int i = 0;
443
444 for (i = 0; i < N; i++) {
445 __riscv_vsse16(reinterpret_cast<_Float16*>(&buffer[i]), N * sizeof(Eigen::half), kernel.packet[i],
446 unpacket_traits<Packet1Xh>::size);
447 }
448
449 for (i = 0; i < N; i++) {
450 kernel.packet[i] = __riscv_vle16_v_f16m1(reinterpret_cast<_Float16*>(&buffer[i * unpacket_traits<Packet1Xh>::size]),
451 unpacket_traits<Packet1Xh>::size);
452 }
453}
454
455EIGEN_STRONG_INLINE Packet2Xf half2float(const Packet1Xh& a) {
456 return __riscv_vfwcvt_f_f_v_f32m2(a, unpacket_traits<Packet2Xf>::size);
457}
458
459EIGEN_STRONG_INLINE Packet1Xh float2half(const Packet2Xf& a) {
460 return __riscv_vfncvt_f_f_w_f16m1(a, unpacket_traits<Packet1Xh>::size);
461}
462
463/********************************* Packet2Xh ************************************/
464
465EIGEN_STRONG_INLINE Packet2Xh __riscv_vreinterpret_v_u32m2_f16m2(const Packet2Xu& a) {
466 return __riscv_vreinterpret_v_u16m2_f16m2(__riscv_vreinterpret_v_u32m2_u16m2(a));
467}
468
469template <>
470EIGEN_STRONG_INLINE Packet2Xh ptrue<Packet2Xh>(const Packet2Xh& /*a*/) {
471 Packet2Xh r = __riscv_vreinterpret_f16m2(__riscv_vmv_v_x_u16m2(0xffffu, unpacket_traits<Packet2Xh>::size));
472 EIGEN_FAST_MATH_CONSTANT_BARRIER(r);
473 return r;
474}
475
476template <>
477EIGEN_STRONG_INLINE Packet2Xh pzero<Packet2Xh>(const Packet2Xh& /*a*/) {
478 return __riscv_vfmv_v_f_f16m2(static_cast<_Float16>(0.0), unpacket_traits<Packet2Xh>::size);
479}
480
481template <>
482EIGEN_STRONG_INLINE Packet2Xh pabs(const Packet2Xh& a) {
483 return __riscv_vfabs_v_f16m2(a, unpacket_traits<Packet2Xh>::size);
484}
485
486template <>
487EIGEN_STRONG_INLINE Packet2Xh pabsdiff(const Packet2Xh& a, const Packet2Xh& b) {
488 return __riscv_vfabs_v_f16m2(__riscv_vfsub_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size),
489 unpacket_traits<Packet2Xh>::size);
490}
491
492template <>
493EIGEN_STRONG_INLINE Packet2Xh pset1<Packet2Xh>(const Eigen::half& from) {
494 return __riscv_vfmv_v_f_f16m2(numext::bit_cast<_Float16>(from), unpacket_traits<Packet2Xh>::size);
495}
496
497template <>
498EIGEN_STRONG_INLINE Packet2Xh pset1frombits<Packet2Xh>(numext::uint16_t from) {
499 return __riscv_vreinterpret_f16m2(__riscv_vmv_v_x_u16m2(from, unpacket_traits<Packet2Xh>::size));
500}
501
502template <>
503EIGEN_STRONG_INLINE Packet2Xh plset<Packet2Xh>(const Eigen::half& a) {
504 Packet2Xh idx = __riscv_vfcvt_f_x_v_f16m2(
505 __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vid_v_u16m2(unpacket_traits<Packet4Xs>::size)),
506 unpacket_traits<Packet2Xh>::size);
507 return __riscv_vfadd_vf_f16m2(idx, numext::bit_cast<_Float16>(a), unpacket_traits<Packet2Xh>::size);
508}
509
510template <>
511EIGEN_STRONG_INLINE void pbroadcast4<Packet2Xh>(const Eigen::half* a, Packet2Xh& a0, Packet2Xh& a1, Packet2Xh& a2,
512 Packet2Xh& a3) {
513 vfloat16m2_t aa = __riscv_vle16_v_f16m2(reinterpret_cast<const _Float16*>(a), 4);
514 a0 = __riscv_vrgather_vx_f16m2(aa, 0, unpacket_traits<Packet2Xh>::size);
515 a1 = __riscv_vrgather_vx_f16m2(aa, 1, unpacket_traits<Packet2Xh>::size);
516 a2 = __riscv_vrgather_vx_f16m2(aa, 2, unpacket_traits<Packet2Xh>::size);
517 a3 = __riscv_vrgather_vx_f16m2(aa, 3, unpacket_traits<Packet2Xh>::size);
518}
519
520template <>
521EIGEN_STRONG_INLINE Packet2Xh padd<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
522 return __riscv_vfadd_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
523}
524
525template <>
526EIGEN_STRONG_INLINE Packet2Xh psub<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
527 return __riscv_vfsub_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
528}
529
530template <>
531EIGEN_STRONG_INLINE Packet2Xh pnegate(const Packet2Xh& a) {
532 return __riscv_vfneg_v_f16m2(a, unpacket_traits<Packet2Xh>::size);
533}
534
535template <>
536EIGEN_STRONG_INLINE Packet2Xh psignbit(const Packet2Xh& a) {
537 return __riscv_vreinterpret_v_i16m2_f16m2(
538 __riscv_vsra_vx_i16m2(__riscv_vreinterpret_v_f16m2_i16m2(a), 15, unpacket_traits<Packet2Xs>::size));
539}
540
541template <>
542EIGEN_STRONG_INLINE Packet2Xh pmul<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
543 return __riscv_vfmul_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
544}
545
546template <>
547EIGEN_STRONG_INLINE Packet2Xh pdiv<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
548 return __riscv_vfdiv_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
549}
550
551template <>
552EIGEN_STRONG_INLINE Packet2Xh pmadd(const Packet2Xh& a, const Packet2Xh& b, const Packet2Xh& c) {
553 return __riscv_vfmadd_vv_f16m2(a, b, c, unpacket_traits<Packet2Xh>::size);
554}
555
556template <>
557EIGEN_STRONG_INLINE Packet2Xh pmsub(const Packet2Xh& a, const Packet2Xh& b, const Packet2Xh& c) {
558 return __riscv_vfmsub_vv_f16m2(a, b, c, unpacket_traits<Packet2Xh>::size);
559}
560
561template <>
562EIGEN_STRONG_INLINE Packet2Xh pnmadd(const Packet2Xh& a, const Packet2Xh& b, const Packet2Xh& c) {
563 return __riscv_vfnmsub_vv_f16m2(a, b, c, unpacket_traits<Packet2Xh>::size);
564}
565
566template <>
567EIGEN_STRONG_INLINE Packet2Xh pnmsub(const Packet2Xh& a, const Packet2Xh& b, const Packet2Xh& c) {
568 return __riscv_vfnmadd_vv_f16m2(a, b, c, unpacket_traits<Packet2Xh>::size);
569}
570
571template <>
572struct pminmax_propagates_nan<Packet2Xh> : bool_constant<true> {};
573
574template <>
575EIGEN_STRONG_INLINE Packet2Xh pmin<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
576 const Eigen::half nan = (std::numeric_limits<Eigen::half>::quiet_NaN)();
577 Packet2Xh nans = __riscv_vfmv_v_f_f16m2(numext::bit_cast<_Float16>(nan), unpacket_traits<Packet2Xh>::size);
578 PacketMask8 mask = __riscv_vmfeq_vv_f16m2_b8(a, a, unpacket_traits<Packet2Xh>::size);
579 PacketMask8 mask2 = __riscv_vmfeq_vv_f16m2_b8(b, b, unpacket_traits<Packet2Xh>::size);
580 mask = __riscv_vmand_mm_b8(mask, mask2, unpacket_traits<Packet2Xh>::size);
581
582 return __riscv_vfmin_vv_f16m2_tumu(mask, nans, a, b, unpacket_traits<Packet2Xh>::size);
583}
584
585template <>
586EIGEN_STRONG_INLINE Packet2Xh pmin<PropagateNumbers, Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
587 return __riscv_vfmin_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
588}
589
590template <>
591EIGEN_STRONG_INLINE Packet2Xh pmax<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
592 const Eigen::half nan = (std::numeric_limits<Eigen::half>::quiet_NaN)();
593 Packet2Xh nans = __riscv_vfmv_v_f_f16m2(numext::bit_cast<_Float16>(nan), unpacket_traits<Packet2Xh>::size);
594 PacketMask8 mask = __riscv_vmfeq_vv_f16m2_b8(a, a, unpacket_traits<Packet2Xh>::size);
595 PacketMask8 mask2 = __riscv_vmfeq_vv_f16m2_b8(b, b, unpacket_traits<Packet2Xh>::size);
596 mask = __riscv_vmand_mm_b8(mask, mask2, unpacket_traits<Packet2Xh>::size);
597
598 return __riscv_vfmax_vv_f16m2_tumu(mask, nans, a, b, unpacket_traits<Packet2Xh>::size);
599}
600
601template <>
602EIGEN_STRONG_INLINE Packet2Xh pmax<PropagateNumbers, Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
603 return __riscv_vfmax_vv_f16m2(a, b, unpacket_traits<Packet2Xh>::size);
604}
605
606template <>
607EIGEN_STRONG_INLINE Packet2Xh pcmp_le<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
608 PacketMask8 mask = __riscv_vmfle_vv_f16m2_b8(a, b, unpacket_traits<Packet2Xh>::size);
609 return __riscv_vmerge_vvm_f16m2(pzero<Packet2Xh>(a), ptrue<Packet2Xh>(a), mask, unpacket_traits<Packet2Xh>::size);
610}
611
612template <>
613EIGEN_STRONG_INLINE Packet2Xh pcmp_lt<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
614 PacketMask8 mask = __riscv_vmflt_vv_f16m2_b8(a, b, unpacket_traits<Packet2Xh>::size);
615 return __riscv_vmerge_vvm_f16m2(pzero<Packet2Xh>(a), ptrue<Packet2Xh>(a), mask, unpacket_traits<Packet2Xh>::size);
616}
617
618template <>
619EIGEN_STRONG_INLINE Packet2Xh pcmp_eq<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
620 PacketMask8 mask = __riscv_vmfeq_vv_f16m2_b8(a, b, unpacket_traits<Packet2Xh>::size);
621 return __riscv_vmerge_vvm_f16m2(pzero<Packet2Xh>(a), ptrue<Packet2Xh>(a), mask, unpacket_traits<Packet2Xh>::size);
622}
623
624template <>
625EIGEN_STRONG_INLINE Packet2Xh pcmp_lt_or_nan<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
626 PacketMask8 mask = __riscv_vmfge_vv_f16m2_b8(a, b, unpacket_traits<Packet2Xh>::size);
627 return __riscv_vfmerge_vfm_f16m2(ptrue<Packet2Xh>(a), static_cast<_Float16>(0.0), mask,
628 unpacket_traits<Packet2Xh>::size);
629}
630
631EIGEN_STRONG_INLINE Packet2Xh pselect(const PacketMask8& mask, const Packet2Xh& a, const Packet2Xh& b) {
632 return __riscv_vmerge_vvm_f16m2(b, a, mask, unpacket_traits<Packet2Xh>::size);
633}
634
635EIGEN_STRONG_INLINE Packet2Xh pselect(const Packet2Xh& mask, const Packet2Xh& a, const Packet2Xh& b) {
636 PacketMask8 mask2 =
637 __riscv_vmsne_vx_i16m2_b8(__riscv_vreinterpret_v_f16m2_i16m2(mask), 0, unpacket_traits<Packet2Xh>::size);
638 return __riscv_vreinterpret_v_i16m2_f16m2(__riscv_vmerge_vvm_i16m2(__riscv_vreinterpret_v_f16m2_i16m2(b),
639 __riscv_vreinterpret_v_f16m2_i16m2(a), mask2,
640 unpacket_traits<Packet2Xh>::size));
641}
642
643// Logical Operations are not supported for half, so reinterpret casts
644template <>
645EIGEN_STRONG_INLINE Packet2Xh pand<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
646 return __riscv_vreinterpret_v_u16m2_f16m2(__riscv_vand_vv_u16m2(
647 __riscv_vreinterpret_v_f16m2_u16m2(a), __riscv_vreinterpret_v_f16m2_u16m2(b), unpacket_traits<Packet2Xh>::size));
648}
649
650template <>
651EIGEN_STRONG_INLINE Packet2Xh por<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
652 return __riscv_vreinterpret_v_u16m2_f16m2(__riscv_vor_vv_u16m2(
653 __riscv_vreinterpret_v_f16m2_u16m2(a), __riscv_vreinterpret_v_f16m2_u16m2(b), unpacket_traits<Packet2Xh>::size));
654}
655
656template <>
657EIGEN_STRONG_INLINE Packet2Xh pxor<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
658 return __riscv_vreinterpret_v_u16m2_f16m2(__riscv_vxor_vv_u16m2(
659 __riscv_vreinterpret_v_f16m2_u16m2(a), __riscv_vreinterpret_v_f16m2_u16m2(b), unpacket_traits<Packet2Xh>::size));
660}
661
662template <>
663EIGEN_STRONG_INLINE Packet2Xh pandnot<Packet2Xh>(const Packet2Xh& a, const Packet2Xh& b) {
664 return __riscv_vreinterpret_v_i16m2_f16m2(
665 pandnot<Packet2Xs>(__riscv_vreinterpret_v_f16m2_i16m2(a), __riscv_vreinterpret_v_f16m2_i16m2(b)));
666}
667
668template <>
669EIGEN_STRONG_INLINE Packet2Xh pnot<Packet2Xh>(const Packet2Xh& a) {
670 return __riscv_vreinterpret_v_u16m2_f16m2(
671 __riscv_vnot_v_u16m2(__riscv_vreinterpret_v_f16m2_u16m2(a), unpacket_traits<Packet2Xh>::size));
672}
673
674template <>
675EIGEN_STRONG_INLINE Packet2Xh pload<Packet2Xh>(const Eigen::half* from) {
676 EIGEN_DEBUG_ALIGNED_LOAD return __riscv_vle16_v_f16m2(reinterpret_cast<const _Float16*>(from),
677 unpacket_traits<Packet2Xh>::size);
678}
679
680template <>
681EIGEN_STRONG_INLINE Packet2Xh ploadu<Packet2Xh>(const Eigen::half* from) {
682 EIGEN_DEBUG_UNALIGNED_LOAD return __riscv_vle16_v_f16m2(reinterpret_cast<const _Float16*>(from),
683 unpacket_traits<Packet2Xh>::size);
684}
685
686template <>
687EIGEN_STRONG_INLINE Packet2Xh ploaddup<Packet2Xh>(const Eigen::half* from) {
688 return __riscv_vreinterpret_v_i16m2_f16m2(ploaddup<Packet2Xs>(reinterpret_cast<const numext::int16_t*>(from)));
689}
690
691template <>
692EIGEN_STRONG_INLINE Packet2Xh ploadquad<Packet2Xh>(const Eigen::half* from) {
693 return __riscv_vreinterpret_v_i16m2_f16m2(ploadquad<Packet2Xs>(reinterpret_cast<const numext::int16_t*>(from)));
694}
695
696template <>
697EIGEN_STRONG_INLINE void pstore<Eigen::half>(Eigen::half* to, const Packet2Xh& from) {
698 EIGEN_DEBUG_ALIGNED_STORE __riscv_vse16_v_f16m2(reinterpret_cast<_Float16*>(to), from,
699 unpacket_traits<Packet2Xh>::size);
700}
701
702template <>
703EIGEN_STRONG_INLINE void pstoreu<Eigen::half>(Eigen::half* to, const Packet2Xh& from) {
704 EIGEN_DEBUG_UNALIGNED_STORE __riscv_vse16_v_f16m2(reinterpret_cast<_Float16*>(to), from,
705 unpacket_traits<Packet2Xh>::size);
706}
707
708template <>
709EIGEN_DEVICE_FUNC inline Packet2Xh pgather<Eigen::half, Packet2Xh>(const Eigen::half* from, Index stride) {
710 return __riscv_vlse16_v_f16m2(reinterpret_cast<const _Float16*>(from), stride * sizeof(Eigen::half),
711 unpacket_traits<Packet2Xh>::size);
712}
713
714template <>
715EIGEN_DEVICE_FUNC inline void pscatter<Eigen::half, Packet2Xh>(Eigen::half* to, const Packet2Xh& from, Index stride) {
716 __riscv_vsse16(reinterpret_cast<_Float16*>(to), stride * sizeof(Eigen::half), from, unpacket_traits<Packet2Xh>::size);
717}
718
719template <>
720EIGEN_STRONG_INLINE Eigen::half pfirst<Packet2Xh>(const Packet2Xh& a) {
721 return numext::bit_cast<Eigen::half>(__riscv_vfmv_f_s_f16m2_f16(a));
722}
723
724template <>
725EIGEN_STRONG_INLINE Packet2Xh psqrt(const Packet2Xh& a) {
726 return __riscv_vfsqrt_v_f16m2(a, unpacket_traits<Packet2Xh>::size);
727}
728
729template <>
730EIGEN_STRONG_INLINE Packet2Xh print<Packet2Xh>(const Packet2Xh& a) {
731 const Packet2Xh limit = pset1<Packet2Xh>(static_cast<Eigen::half>(1 << 10));
732 const Packet2Xh abs_a = pabs(a);
733
734 PacketMask8 mask = __riscv_vmfne_vv_f16m2_b8(a, a, unpacket_traits<Packet2Xh>::size);
735 const Packet2Xh x = __riscv_vfadd_vv_f16m2_tumu(mask, a, a, a, unpacket_traits<Packet2Xh>::size);
736 const Packet2Xh new_x = __riscv_vfcvt_f_x_v_f16m2(__riscv_vfcvt_x_f_v_i16m2(a, unpacket_traits<Packet2Xh>::size),
737 unpacket_traits<Packet2Xh>::size);
738
739 mask = __riscv_vmflt_vv_f16m2_b8(abs_a, limit, unpacket_traits<Packet2Xh>::size);
740 Packet2Xh signed_x = __riscv_vfsgnj_vv_f16m2(new_x, x, unpacket_traits<Packet2Xh>::size);
741 return __riscv_vmerge_vvm_f16m2(x, signed_x, mask, unpacket_traits<Packet2Xh>::size);
742}
743
744template <>
745EIGEN_STRONG_INLINE Packet2Xh pfloor<Packet2Xh>(const Packet2Xh& a) {
746 Packet2Xh tmp = print<Packet2Xh>(a);
747 // If greater, subtract one.
748 PacketMask8 mask = __riscv_vmflt_vv_f16m2_b8(a, tmp, unpacket_traits<Packet2Xh>::size);
749 return __riscv_vfsub_vf_f16m2_tumu(mask, tmp, tmp, static_cast<_Float16>(1.0), unpacket_traits<Packet2Xh>::size);
750}
751
752template <>
753EIGEN_STRONG_INLINE Packet2Xh preverse(const Packet2Xh& a) {
754 Packet2Xsu idx = __riscv_vrsub_vx_u16m2(__riscv_vid_v_u16m2(unpacket_traits<Packet2Xh>::size),
755 unpacket_traits<Packet2Xh>::size - 1, unpacket_traits<Packet2Xh>::size);
756 return __riscv_vrgather_vv_f16m2(a, idx, unpacket_traits<Packet2Xh>::size);
757}
758
759template <>
760EIGEN_STRONG_INLINE Eigen::half predux<Packet2Xh>(const Packet2Xh& a) {
761 return static_cast<Eigen::half>(__riscv_vfmv_f(__riscv_vfredusum_vs_f16m2_f16m1(
762 a, __riscv_vfmv_v_f_f16m1(static_cast<_Float16>(0.0), unpacket_traits<Packet2Xh>::size / 2),
763 unpacket_traits<Packet2Xh>::size)));
764}
765
766template <>
767EIGEN_STRONG_INLINE bool predux_any(const Packet2Xh& a) {
768 const PacketMask8 mask =
769 __riscv_vmsne_vx_u16m2_b8(__riscv_vreinterpret_v_f16m2_u16m2(a), 0, unpacket_traits<Packet2Xh>::size);
770 return __riscv_vcpop_m_b8(mask, unpacket_traits<Packet2Xh>::size) != 0;
771}
772
773template <>
774EIGEN_STRONG_INLINE bool predux_all(const Packet2Xh& a) {
775 const PacketMask8 mask = __riscv_vmfeq_vf_f16m2_b8(a, static_cast<_Float16>(0.0), unpacket_traits<Packet2Xh>::size);
776 return __riscv_vcpop_m_b8(mask, unpacket_traits<Packet2Xh>::size) == 0;
777}
778
779template <>
780EIGEN_STRONG_INLINE Eigen::half predux_mul<Packet2Xh>(const Packet2Xh& a) {
781 return predux_mul<Packet1Xh>(__riscv_vfmul_vv_f16m1(
782 __riscv_vget_v_f16m2_f16m1(a, 0), __riscv_vget_v_f16m2_f16m1(a, 1), unpacket_traits<Packet1Xh>::size));
783}
784
785template <>
786EIGEN_STRONG_INLINE Eigen::half predux_min<Packet2Xh>(const Packet2Xh& a) {
787 return static_cast<Eigen::half>(__riscv_vfmv_f(
788 __riscv_vfredmin_vs_f16m2_f16m1(a, __riscv_vget_v_f16m2_f16m1(a, 0), unpacket_traits<Packet2Xh>::size)));
789}
790
791template <>
792EIGEN_STRONG_INLINE Eigen::half predux_max<Packet2Xh>(const Packet2Xh& a) {
793 return static_cast<Eigen::half>(__riscv_vfmv_f(
794 __riscv_vfredmax_vs_f16m2_f16m1(a, __riscv_vget_v_f16m2_f16m1(a, 0), unpacket_traits<Packet2Xh>::size)));
795}
796
797template <int N>
798EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2Xh, N>& kernel) {
799 Eigen::half buffer[unpacket_traits<Packet2Xh>::size * N];
800 int i = 0;
801
802 for (i = 0; i < N; i++) {
803 __riscv_vsse16(reinterpret_cast<_Float16*>(&buffer[i]), N * sizeof(Eigen::half), kernel.packet[i],
804 unpacket_traits<Packet2Xh>::size);
805 }
806
807 for (i = 0; i < N; i++) {
808 kernel.packet[i] = __riscv_vle16_v_f16m2(reinterpret_cast<_Float16*>(&buffer[i * unpacket_traits<Packet2Xh>::size]),
809 unpacket_traits<Packet2Xh>::size);
810 }
811}
812
813EIGEN_STRONG_INLINE Packet4Xf half2float(const Packet2Xh& a) {
814 return __riscv_vfwcvt_f_f_v_f32m4(a, unpacket_traits<Packet4Xf>::size);
815}
816
817EIGEN_STRONG_INLINE Packet2Xh float2half(const Packet4Xf& a) {
818 return __riscv_vfncvt_f_f_w_f16m2(a, unpacket_traits<Packet2Xh>::size);
819}
820
821template <typename Packet = Packet2Xh>
822EIGEN_STRONG_INLINE
823 std::enable_if_t<std::is_same<Packet, Packet2Xh>::value && (unpacket_traits<Packet2Xh>::size % 8) == 0, Packet1Xh>
824 predux_half(const Packet2Xh& a) {
825 return __riscv_vfadd_vv_f16m1(__riscv_vget_v_f16m2_f16m1(a, 0), __riscv_vget_v_f16m2_f16m1(a, 1),
826 unpacket_traits<Packet1Xh>::size);
827}
828
829F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, pcos)
830F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, pexp)
831F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, pexpm1)
832F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, plog)
833F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, plog1p)
834F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, plog2)
835F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, preciprocal)
836F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, prsqrt)
837F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, psin)
838F16_PACKET_FUNCTION(Packet2Xf, Packet1Xh, ptanh)
839
840F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, pcos)
841F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, pexp)
842F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, pexpm1)
843F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, plog)
844F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, plog1p)
845F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, plog2)
846F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, preciprocal)
847F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, prsqrt)
848F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, psin)
849F16_PACKET_FUNCTION(Packet4Xf, Packet2Xh, ptanh)
850
851/********************************* casting ************************************/
852
853template <>
854struct type_casting_traits<_Float16, numext::int16_t> {
855 enum { VectorizedCast = 1, SrcCoeffRatio = 1, TgtCoeffRatio = 1 };
856};
857
858template <>
859struct type_casting_traits<numext::int16_t, _Float16> {
860 enum { VectorizedCast = 1, SrcCoeffRatio = 1, TgtCoeffRatio = 1 };
861};
862
863template <>
864EIGEN_STRONG_INLINE Packet1Xh pcast<Packet1Xs, Packet1Xh>(const Packet1Xs& a) {
865 return __riscv_vfcvt_f_x_v_f16m1(a, unpacket_traits<Packet1Xs>::size);
866}
867
868template <>
869EIGEN_STRONG_INLINE Packet1Xs pcast<Packet1Xh, Packet1Xs>(const Packet1Xh& a) {
870 return __riscv_vfcvt_rtz_x_f_v_i16m1(a, unpacket_traits<Packet1Xh>::size);
871}
872
873template <>
874EIGEN_STRONG_INLINE Packet1Xh preinterpret<Packet1Xh, Packet1Xs>(const Packet1Xs& a) {
875 return __riscv_vreinterpret_v_i16m1_f16m1(a);
876}
877
878template <>
879EIGEN_STRONG_INLINE Packet1Xs preinterpret<Packet1Xs, Packet1Xh>(const Packet1Xh& a) {
880 return __riscv_vreinterpret_v_f16m1_i16m1(a);
881}
882
883template <>
884EIGEN_STRONG_INLINE Packet2Xh pcast<Packet2Xs, Packet2Xh>(const Packet2Xs& a) {
885 return __riscv_vfcvt_f_x_v_f16m2(a, unpacket_traits<Packet2Xs>::size);
886}
887
888template <>
889EIGEN_STRONG_INLINE Packet2Xs pcast<Packet2Xh, Packet2Xs>(const Packet2Xh& a) {
890 return __riscv_vfcvt_rtz_x_f_v_i16m2(a, unpacket_traits<Packet2Xh>::size);
891}
892
893template <>
894EIGEN_STRONG_INLINE Packet2Xh preinterpret<Packet2Xh, Packet2Xs>(const Packet2Xs& a) {
895 return __riscv_vreinterpret_v_i16m2_f16m2(a);
896}
897
898template <>
899EIGEN_STRONG_INLINE Packet2Xs preinterpret<Packet2Xs, Packet2Xh>(const Packet2Xh& a) {
900 return __riscv_vreinterpret_v_f16m2_i16m2(a);
901}
902
903template <>
904EIGEN_STRONG_INLINE Packet4Xs pcast<Packet1Xh, Packet4Xs>(const Packet1Xh& a, const Packet1Xh& b, const Packet1Xh& c,
905 const Packet1Xh& d) {
906 return __riscv_vcreate_v_i16m1_i16m4(__riscv_vfcvt_rtz_x_f_v_i16m1(a, unpacket_traits<Packet1Xh>::size),
907 __riscv_vfcvt_rtz_x_f_v_i16m1(b, unpacket_traits<Packet1Xh>::size),
908 __riscv_vfcvt_rtz_x_f_v_i16m1(c, unpacket_traits<Packet1Xh>::size),
909 __riscv_vfcvt_rtz_x_f_v_i16m1(d, unpacket_traits<Packet1Xh>::size));
910}
911
912template <>
913EIGEN_STRONG_INLINE Packet2Xh pcast<Packet1Xs, Packet2Xh>(const Packet1Xs& a, const Packet1Xs& b) {
914 return __riscv_vcreate_v_f16m1_f16m2(__riscv_vfcvt_f_x_v_f16m1(a, unpacket_traits<Packet1Xs>::size),
915 __riscv_vfcvt_f_x_v_f16m1(b, unpacket_traits<Packet1Xs>::size));
916}
917
918template <>
919EIGEN_STRONG_INLINE Packet2Xh pcast<Packet1Xh, Packet2Xh>(const Packet1Xh& a, const Packet1Xh& b) {
920 return __riscv_vcreate_v_f16m1_f16m2(a, b);
921}
922
923template <>
924EIGEN_STRONG_INLINE Packet2Xs pcast<Packet1Xh, Packet2Xs>(const Packet1Xh& a, const Packet1Xh& b) {
925 return __riscv_vcreate_v_i16m1_i16m2(__riscv_vfcvt_rtz_x_f_v_i16m1(a, unpacket_traits<Packet1Xh>::size),
926 __riscv_vfcvt_rtz_x_f_v_i16m1(b, unpacket_traits<Packet1Xh>::size));
927}
928
929} // namespace internal
930} // namespace Eigen
931
932#endif // EIGEN_PACKET_MATH_FP16_RVV10_H