codekingpro/portable-devtools
114k
1/*
2* Copyright 1993-2023 NVIDIA Corporation. All rights reserved.
3*
4* NOTICE TO LICENSEE:
5*
6* This source code and/or documentation ("Licensed Deliverables") are
7* subject to NVIDIA intellectual property rights under U.S. and
8* international Copyright laws.
9*
10* These Licensed Deliverables contained herein is PROPRIETARY and
11* CONFIDENTIAL to NVIDIA and is being provided under the terms and
12* conditions of a form of NVIDIA software license agreement by and
13* between NVIDIA and Licensee ("License Agreement") or electronically
14* accepted by Licensee. Notwithstanding any terms or conditions to
15* the contrary in the License Agreement, reproduction or disclosure
16* of the Licensed Deliverables to any third party without the express
17* written consent of NVIDIA is prohibited.
18*
19* NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
20* LICENSE AGREEMENT, NVIDIA MAKES NO REPRESENTATION ABOUT THE
21* SUITABILITY OF THESE LICENSED DELIVERABLES FOR ANY PURPOSE. IT IS
22* PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.
23* NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE LICENSED
24* DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,
25* NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
26* NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE
27* LICENSE AGREEMENT, IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY
28* SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY
29* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
31* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
32* OF THESE LICENSED DELIVERABLES.
33*
34* U.S. Government End Users. These Licensed Deliverables are a
35* "commercial item" as that term is defined at 48 C.F.R. 2.101 (OCT
36* 1995), consisting of "commercial computer software" and "commercial
37* computer software documentation" as such terms are used in 48
38* C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government
39* only as a commercial end item. Consistent with 48 C.F.R.12.212 and
40* 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all
41* U.S. Government End Users acquire the Licensed Deliverables with
42* only those rights set forth herein.
43*
44* Any use of the Licensed Deliverables in individual and commercial
45* software must include, in the user documentation and internal
46* comments to the code, the above Disclaimer and U.S. Government End
47* Users Notice.
48*/
49
50#if !defined(__CUDA_FP16_HPP__)
51#define __CUDA_FP16_HPP__
52
53#if !defined(__CUDA_FP16_H__)
54#error "Do not include this file directly. Instead, include cuda_fp16.h."
55#endif
56
57#if !defined(IF_DEVICE_OR_CUDACC)
58#if defined(__CUDACC__)
59 #define IF_DEVICE_OR_CUDACC(d, c, f) NV_IF_ELSE_TARGET(NV_IS_DEVICE, d, c)
60#else
61 #define IF_DEVICE_OR_CUDACC(d, c, f) NV_IF_ELSE_TARGET(NV_IS_DEVICE, d, f)
62#endif
63#endif
64
65/* Macros for half & half2 binary arithmetic */
66#define __BINARY_OP_HALF_MACRO(name) /* do */ {\
67 __half val; \
68 asm( "{" __CUDA_FP16_STRINGIFY(name) ".f16 %0,%1,%2;\n}" \
69 :"=h"(__HALF_TO_US(val)) : "h"(__HALF_TO_CUS(a)),"h"(__HALF_TO_CUS(b))); \
70 return val; \
71} /* while(0) */
72#define __BINARY_OP_HALF2_MACRO(name) /* do */ {\
73 __half2 val; \
74 asm( "{" __CUDA_FP16_STRINGIFY(name) ".f16x2 %0,%1,%2;\n}" \
75 :"=r"(__HALF2_TO_UI(val)) : "r"(__HALF2_TO_CUI(a)),"r"(__HALF2_TO_CUI(b))); \
76 return val; \
77} /* while(0) */
78#define __TERNARY_OP_HALF_MACRO(name) /* do */ {\
79 __half val; \
80 asm( "{" __CUDA_FP16_STRINGIFY(name) ".f16 %0,%1,%2,%3;\n}" \
81 :"=h"(__HALF_TO_US(val)) : "h"(__HALF_TO_CUS(a)),"h"(__HALF_TO_CUS(b)),"h"(__HALF_TO_CUS(c))); \
82 return val; \
83} /* while(0) */
84#define __TERNARY_OP_HALF2_MACRO(name) /* do */ {\
85 __half2 val; \
86 asm( "{" __CUDA_FP16_STRINGIFY(name) ".f16x2 %0,%1,%2,%3;\n}" \
87 :"=r"(__HALF2_TO_UI(val)) : "r"(__HALF2_TO_CUI(a)),"r"(__HALF2_TO_CUI(b)),"r"(__HALF2_TO_CUI(c))); \
88 return val; \
89} /* while(0) */
90
91/* All other definitions in this file are only visible to C++ compilers */
92#if defined(__cplusplus)
93
94/**
95 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
96 * \brief Defines floating-point positive infinity value for the \p half data type
97 */
98#define CUDART_INF_FP16 __ushort_as_half((unsigned short)0x7C00U)
99/**
100 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
101 * \brief Defines canonical NaN value for the \p half data type
102 */
103#define CUDART_NAN_FP16 __ushort_as_half((unsigned short)0x7FFFU)
104/**
105 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
106 * \brief Defines a minimum representable (denormalized) value for the \p half data type
107 */
108#define CUDART_MIN_DENORM_FP16 __ushort_as_half((unsigned short)0x0001U)
109/**
110 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
111 * \brief Defines a maximum representable value for the \p half data type
112 */
113#define CUDART_MAX_NORMAL_FP16 __ushort_as_half((unsigned short)0x7BFFU)
114/**
115 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
116 * \brief Defines a negative zero value for the \p half data type
117 */
118#define CUDART_NEG_ZERO_FP16 __ushort_as_half((unsigned short)0x8000U)
119/**
120 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
121 * \brief Defines a positive zero value for the \p half data type
122 */
123#define CUDART_ZERO_FP16 __ushort_as_half((unsigned short)0x0000U)
124/**
125 * \ingroup CUDA_MATH_INTRINSIC_HALF_CONSTANTS
126 * \brief Defines a value of 1.0 for the \p half data type
127 */
128#define CUDART_ONE_FP16 __ushort_as_half((unsigned short)0x3C00U)
129
130__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const __half_raw &hr) { __x = hr.x; return *this; }
131__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ volatile __half &__half::operator=(const __half_raw &hr) volatile { __x = hr.x; return *this; }
132__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ volatile __half &__half::operator=(const volatile __half_raw &hr) volatile { __x = hr.x; return *this; }
133__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator __half_raw() const { __half_raw ret; ret.x = __x; return ret; }
134__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator __half_raw() const volatile { __half_raw ret; ret.x = __x; return ret; }
135#if !defined(__CUDA_NO_HALF_CONVERSIONS__)
136__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator float() const { return __half2float(*this); }
137__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const float f) { __x = __float2half(f).__x; return *this; }
138__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const double f) { __x = __double2half(f).__x; return *this; }
139#if !(defined __CUDA_FP16_DISABLE_IMPLICIT_INTEGER_CONVERTS_FOR_HOST_COMPILERS__) || (defined __CUDACC__)
140__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator signed char() const { return __half2char_rz(*this); }
141__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator unsigned char() const { return __half2uchar_rz(*this); }
142__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator char() const {
143 char value;
144 /* Suppress VS warning: warning C4127: conditional expression is constant */
145#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
146#pragma warning (push)
147#pragma warning (disable: 4127)
148#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
149 if (((char)-1) < (char)0)
150#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
151#pragma warning (pop)
152#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
153 {
154 value = static_cast<char>(__half2char_rz(*this));
155 }
156 else
157 {
158 value = static_cast<char>(__half2uchar_rz(*this));
159 }
160 return value;
161}
162__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator short() const { return __half2short_rz(*this); }
163__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator unsigned short() const { return __half2ushort_rz(*this); }
164__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator int() const { return __half2int_rz(*this); }
165__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator unsigned int() const { return __half2uint_rz(*this); }
166__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator long() const {
167 long retval;
168 /* Suppress VS warning: warning C4127: conditional expression is constant */
169#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
170#pragma warning (push)
171#pragma warning (disable: 4127)
172#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
173 if (sizeof(long) == sizeof(long long))
174#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
175#pragma warning (pop)
176#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
177 {
178 retval = static_cast<long>(__half2ll_rz(*this));
179 }
180 else
181 {
182 retval = static_cast<long>(__half2int_rz(*this));
183 }
184 return retval;
185}
186__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator unsigned long() const {
187 unsigned long retval;
188 /* Suppress VS warning: warning C4127: conditional expression is constant */
189#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
190#pragma warning (push)
191#pragma warning (disable: 4127)
192#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
193 if (sizeof(unsigned long) == sizeof(unsigned long long))
194#if defined(_MSC_VER) && !defined(__CUDA_ARCH__)
195#pragma warning (pop)
196#endif /* _MSC_VER && !defined(__CUDA_ARCH__) */
197 {
198 retval = static_cast<unsigned long>(__half2ull_rz(*this));
199 }
200 else
201 {
202 retval = static_cast<unsigned long>(__half2uint_rz(*this));
203 }
204 return retval;
205}
206__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator long long() const { return __half2ll_rz(*this); }
207__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half::operator unsigned long long() const { return __half2ull_rz(*this); }
208__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const short val) { __x = __short2half_rn(val).__x; return *this; }
209__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const unsigned short val) { __x = __ushort2half_rn(val).__x; return *this; }
210__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const int val) { __x = __int2half_rn(val).__x; return *this; }
211__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const unsigned int val) { __x = __uint2half_rn(val).__x; return *this; }
212__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const long long val) { __x = __ll2half_rn(val).__x; return *this; }
213__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half &__half::operator=(const unsigned long long val) { __x = __ull2half_rn(val).__x; return *this; }
214#endif /* #if !(defined __CUDA_FP16_DISABLE_IMPLICIT_INTEGER_CONVERTS_FOR_HOST_COMPILERS__) || (defined __CUDACC__) */
215#endif /* !defined(__CUDA_NO_HALF_CONVERSIONS__) */
216#if !defined(__CUDA_NO_HALF_OPERATORS__)
217/* Some basic arithmetic operations expected of a builtin */
218__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator+(const __half &lh, const __half &rh) { return __hadd(lh, rh); }
219__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator-(const __half &lh, const __half &rh) { return __hsub(lh, rh); }
220__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator*(const __half &lh, const __half &rh) { return __hmul(lh, rh); }
221__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator/(const __half &lh, const __half &rh) { return __hdiv(lh, rh); }
222__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator+=(__half &lh, const __half &rh) { lh = __hadd(lh, rh); return lh; }
223__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator-=(__half &lh, const __half &rh) { lh = __hsub(lh, rh); return lh; }
224__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator*=(__half &lh, const __half &rh) { lh = __hmul(lh, rh); return lh; }
225__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator/=(__half &lh, const __half &rh) { lh = __hdiv(lh, rh); return lh; }
226__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator++(__half &h) { __half_raw one; one.x = 0x3C00U; h += one; return h; }
227__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half &operator--(__half &h) { __half_raw one; one.x = 0x3C00U; h -= one; return h; }
228__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator++(__half &h, const int ignored)
229{
230 // ignored on purpose. Parameter only needed to distinguish the function declaration from other types of operators.
231 static_cast<void>(ignored);
232
233 const __half ret = h;
234 __half_raw one;
235 one.x = 0x3C00U;
236 h += one;
237 return ret;
238}
239__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator--(__half &h, const int ignored)
240{
241 // ignored on purpose. Parameter only needed to distinguish the function declaration from other types of operators.
242 static_cast<void>(ignored);
243
244 const __half ret = h;
245 __half_raw one;
246 one.x = 0x3C00U;
247 h -= one;
248 return ret;
249}
250__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator+(const __half &h) { return h; }
251__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half operator-(const __half &h) { return __hneg(h); }
252__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator==(const __half &lh, const __half &rh) { return __heq(lh, rh); }
253__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator!=(const __half &lh, const __half &rh) { return __hneu(lh, rh); }
254__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator> (const __half &lh, const __half &rh) { return __hgt(lh, rh); }
255__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator< (const __half &lh, const __half &rh) { return __hlt(lh, rh); }
256__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator>=(const __half &lh, const __half &rh) { return __hge(lh, rh); }
257__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator<=(const __half &lh, const __half &rh) { return __hle(lh, rh); }
258#endif /* !defined(__CUDA_NO_HALF_OPERATORS__) */
259#if defined(__CPP_VERSION_AT_LEAST_11_FP16)
260__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half2 &__half2::operator=(const __half2 &&src) {
261NV_IF_ELSE_TARGET(NV_IS_DEVICE,
262 __HALF2_TO_UI(*this) = std::move(__HALF2_TO_CUI(src));
263,
264 this->x = src.x;
265 this->y = src.y;
266)
267 return *this;
268}
269#endif /* defined(__CPP_VERSION_AT_LEAST_11_FP16) */
270__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half2 &__half2::operator=(const __half2 &src) {
271NV_IF_ELSE_TARGET(NV_IS_DEVICE,
272 __HALF2_TO_UI(*this) = __HALF2_TO_CUI(src);
273,
274 this->x = src.x;
275 this->y = src.y;
276)
277 return *this;
278}
279__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half2 &__half2::operator=(const __half2_raw &h2r) {
280NV_IF_ELSE_TARGET(NV_IS_DEVICE,
281 __HALF2_TO_UI(*this) = __HALF2_TO_CUI(h2r);
282,
283 __half_raw tr;
284 tr.x = h2r.x;
285 this->x = static_cast<__half>(tr);
286 tr.x = h2r.y;
287 this->y = static_cast<__half>(tr);
288)
289 return *this;
290}
291__CUDA_HOSTDEVICE__ __CUDA_FP16_INLINE__ __half2::operator __half2_raw() const {
292 __half2_raw ret;
293NV_IF_ELSE_TARGET(NV_IS_DEVICE,
294 ret.x = 0U;
295 ret.y = 0U;
296 __HALF2_TO_UI(ret) = __HALF2_TO_CUI(*this);
297,
298 ret.x = static_cast<__half_raw>(this->x).x;
299 ret.y = static_cast<__half_raw>(this->y).x;
300)
301 return ret;
302}
303#if !defined(__CUDA_NO_HALF2_OPERATORS__)
304__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator+(const __half2 &lh, const __half2 &rh) { return __hadd2(lh, rh); }
305__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator-(const __half2 &lh, const __half2 &rh) { return __hsub2(lh, rh); }
306__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator*(const __half2 &lh, const __half2 &rh) { return __hmul2(lh, rh); }
307__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator/(const __half2 &lh, const __half2 &rh) { return __h2div(lh, rh); }
308__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2& operator+=(__half2 &lh, const __half2 &rh) { lh = __hadd2(lh, rh); return lh; }
309__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2& operator-=(__half2 &lh, const __half2 &rh) { lh = __hsub2(lh, rh); return lh; }
310__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2& operator*=(__half2 &lh, const __half2 &rh) { lh = __hmul2(lh, rh); return lh; }
311__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2& operator/=(__half2 &lh, const __half2 &rh) { lh = __h2div(lh, rh); return lh; }
312__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 &operator++(__half2 &h) { __half2_raw one; one.x = 0x3C00U; one.y = 0x3C00U; h = __hadd2(h, one); return h; }
313__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 &operator--(__half2 &h) { __half2_raw one; one.x = 0x3C00U; one.y = 0x3C00U; h = __hsub2(h, one); return h; }
314__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator++(__half2 &h, const int ignored)
315{
316 // ignored on purpose. Parameter only needed to distinguish the function declaration from other types of operators.
317 static_cast<void>(ignored);
318
319 const __half2 ret = h;
320 __half2_raw one;
321 one.x = 0x3C00U;
322 one.y = 0x3C00U;
323 h = __hadd2(h, one);
324 return ret;
325}
326__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator--(__half2 &h, const int ignored)
327{
328 // ignored on purpose. Parameter only needed to distinguish the function declaration from other types of operators.
329 static_cast<void>(ignored);
330
331 const __half2 ret = h;
332 __half2_raw one;
333 one.x = 0x3C00U;
334 one.y = 0x3C00U;
335 h = __hsub2(h, one);
336 return ret;
337}
338__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator+(const __half2 &h) { return h; }
339__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ __half2 operator-(const __half2 &h) { return __hneg2(h); }
340__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator==(const __half2 &lh, const __half2 &rh) { return __hbeq2(lh, rh); }
341__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator!=(const __half2 &lh, const __half2 &rh) { return __hbneu2(lh, rh); }
342__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator>(const __half2 &lh, const __half2 &rh) { return __hbgt2(lh, rh); }
343__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator<(const __half2 &lh, const __half2 &rh) { return __hblt2(lh, rh); }
344__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator>=(const __half2 &lh, const __half2 &rh) { return __hbge2(lh, rh); }
345__CUDA_HOSTDEVICE__ __CUDA_FP16_FORCEINLINE__ bool operator<=(const __half2 &lh, const __half2 &rh) { return __hble2(lh, rh); }
346#endif /* !defined(__CUDA_NO_HALF2_OPERATORS__) */
347
348/* Restore warning for multiple assignment operators */
349#if defined(_MSC_VER) && _MSC_VER >= 1500
350#pragma warning( pop )
351#endif /* defined(_MSC_VER) && _MSC_VER >= 1500 */
352
353/* Restore -Weffc++ warnings from here on */
354#if defined(__GNUC__)
355#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
356#pragma GCC diagnostic pop
357#endif /* __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) */
358#endif /* defined(__GNUC__) */
359
360#undef __CUDA_HOSTDEVICE__
361#undef __CUDA_ALIGN__
362
363#ifndef __CUDACC_RTC__ /* no host functions in NVRTC mode */
364static inline unsigned short __internal_float2half(const float f, unsigned int &sign, unsigned int &remainder)
365{
366 unsigned int x;
367 unsigned int u;
368 unsigned int result;
369#if defined(__CUDACC__)
370 (void)memcpy(&x, &f, sizeof(f));
371#else
372 (void)std::memcpy(&x, &f, sizeof(f));
373#endif
374 u = (x & 0x7fffffffU);
375 sign = ((x >> 16U) & 0x8000U);
376 // NaN/+Inf/-Inf
377 if (u >= 0x7f800000U) {
378 remainder = 0U;
379 result = ((u == 0x7f800000U) ? (sign | 0x7c00U) : 0x7fffU);
380 } else if (u > 0x477fefffU) { // Overflows
381 remainder = 0x80000000U;
382 result = (sign | 0x7bffU);
383 } else if (u >= 0x38800000U) { // Normal numbers
384 remainder = u << 19U;
385 u -= 0x38000000U;
386 result = (sign | (u >> 13U));
387 } else if (u < 0x33000001U) { // +0/-0
388 remainder = u;
389 result = sign;
390 } else { // Denormal numbers
391 const unsigned int exponent = u >> 23U;
392 const unsigned int shift = 0x7eU - exponent;
393 unsigned int mantissa = (u & 0x7fffffU);
394 mantissa |= 0x800000U;
395 remainder = mantissa << (32U - shift);
396 result = (sign | (mantissa >> shift));
397 result &= 0x0000FFFFU;
398 }
399 return static_cast<unsigned short>(result);
400}
401#endif /* #if !defined(__CUDACC_RTC__) */
402
403__CUDA_HOSTDEVICE_FP16_DECL__ __half __double2half(const double a)
404{
405IF_DEVICE_OR_CUDACC(
406 __half val;
407 asm("{ cvt.rn.f16.f64 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "d"(a));
408 return val;
409,
410 __half result;
411 // Perform rounding to 11 bits of precision, convert value
412 // to float and call existing float to half conversion.
413 // By pre-rounding to 11 bits we avoid additional rounding
414 // in float to half conversion.
415 unsigned long long int absa;
416 unsigned long long int ua;
417 (void)memcpy(&ua, &a, sizeof(a));
418 absa = (ua & 0x7fffffffffffffffULL);
419 if ((absa >= 0x40f0000000000000ULL) || (absa <= 0x3e60000000000000ULL))
420 {
421 // |a| >= 2^16 or NaN or |a| <= 2^(-25)
422 // double-rounding is not a problem
423 result = __float2half(static_cast<float>(a));
424 }
425 else
426 {
427 // here 2^(-25) < |a| < 2^16
428 // prepare shifter value such that a + shifter
429 // done in double precision performs round-to-nearest-even
430 // and (a + shifter) - shifter results in a rounded to
431 // 11 bits of precision. Shifter needs to have exponent of
432 // a plus 53 - 11 = 42 and a leading bit in mantissa to guard
433 // against negative values.
434 // So need to have |a| capped to avoid overflow in exponent.
435 // For inputs that are smaller than half precision minnorm
436 // we prepare fixed shifter exponent.
437 unsigned long long shifterBits;
438 if (absa >= 0x3f10000000000000ULL)
439 { // Here if |a| >= 2^(-14)
440 // add 42 to exponent bits
441 shifterBits = (ua & 0x7ff0000000000000ULL) + 0x02A0000000000000ULL;
442 }
443 else
444 { // 2^(-25) < |a| < 2^(-14), potentially results in denormal
445 // set exponent bits to 42 - 14 + bias
446 shifterBits = 0x41B0000000000000ULL;
447 }
448 // set leading mantissa bit to protect against negative inputs
449 shifterBits |= 0x0008000000000000ULL;
450 double shifter;
451 (void)memcpy(&shifter, &shifterBits, sizeof(shifterBits));
452 double aShiftRound = a + shifter;
453
454 // Prevent the compiler from optimizing away a + shifter - shifter
455 // by doing intermediate memcopy and harmless bitwize operation
456 unsigned long long int aShiftRoundBits;
457 (void)memcpy(&aShiftRoundBits, &aShiftRound, sizeof(aShiftRound));
458
459 // the value is positive, so this operation doesn't change anything
460 aShiftRoundBits &= 0x7fffffffffffffffULL;
461
462 (void)memcpy(&aShiftRound, &aShiftRoundBits, sizeof(aShiftRound));
463
464 result = __float2half(static_cast<float>(aShiftRound - shifter));
465 }
466
467 return result;
468,
469 __half result;
470 /*
471 // Perform rounding to 11 bits of precision, convert value
472 // to float and call existing float to half conversion.
473 // By pre-rounding to 11 bits we avoid additional rounding
474 // in float to half conversion.
475 */
476 unsigned long long int absa;
477 unsigned long long int ua;
478 (void)std::memcpy(&ua, &a, sizeof(a));
479 absa = (ua & 0x7fffffffffffffffULL);
480 if ((absa >= 0x40f0000000000000ULL) || (absa <= 0x3e60000000000000ULL))
481 {
482 /*
483 // |a| >= 2^16 or NaN or |a| <= 2^(-25)
484 // double-rounding is not a problem
485 */
486 result = __float2half(static_cast<float>(a));
487 }
488 else
489 {
490 /*
491 // here 2^(-25) < |a| < 2^16
492 // prepare shifter value such that a + shifter
493 // done in double precision performs round-to-nearest-even
494 // and (a + shifter) - shifter results in a rounded to
495 // 11 bits of precision. Shifter needs to have exponent of
496 // a plus 53 - 11 = 42 and a leading bit in mantissa to guard
497 // against negative values.
498 // So need to have |a| capped to avoid overflow in exponent.
499 // For inputs that are smaller than half precision minnorm
500 // we prepare fixed shifter exponent.
501 */
502 unsigned long long shifterBits;
503 if (absa >= 0x3f10000000000000ULL)
504 {
505 /*
506 // Here if |a| >= 2^(-14)
507 // add 42 to exponent bits
508 */
509 shifterBits = (ua & 0x7ff0000000000000ULL) + 0x02A0000000000000ULL;
510 }
511 else
512 {
513 /*
514 // 2^(-25) < |a| < 2^(-14), potentially results in denormal
515 // set exponent bits to 42 - 14 + bias
516 */
517 shifterBits = 0x41B0000000000000ULL;
518 }
519 // set leading mantissa bit to protect against negative inputs
520 shifterBits |= 0x0008000000000000ULL;
521 double shifter;
522 (void)std::memcpy(&shifter, &shifterBits, sizeof(shifterBits));
523 double aShiftRound = a + shifter;
524
525 /*
526 // Prevent the compiler from optimizing away a + shifter - shifter
527 // by doing intermediate memcopy and harmless bitwize operation
528 */
529 unsigned long long int aShiftRoundBits;
530 (void)std::memcpy(&aShiftRoundBits, &aShiftRound, sizeof(aShiftRound));
531
532 // the value is positive, so this operation doesn't change anything
533 aShiftRoundBits &= 0x7fffffffffffffffULL;
534
535 (void)std::memcpy(&aShiftRound, &aShiftRoundBits, sizeof(aShiftRound));
536
537 result = __float2half(static_cast<float>(aShiftRound - shifter));
538 }
539
540 return result;
541)
542}
543__CUDA_HOSTDEVICE_FP16_DECL__ __half __float2half(const float a)
544{
545 __half val;
546NV_IF_ELSE_TARGET(NV_IS_DEVICE,
547 asm("{ cvt.rn.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(a));
548,
549 __half_raw r;
550 unsigned int sign = 0U;
551 unsigned int remainder = 0U;
552 r.x = __internal_float2half(a, sign, remainder);
553 if ((remainder > 0x80000000U) || ((remainder == 0x80000000U) && ((r.x & 0x1U) != 0U))) {
554 r.x++;
555 }
556 val = r;
557)
558 return val;
559}
560__CUDA_HOSTDEVICE_FP16_DECL__ __half __float2half_rn(const float a)
561{
562 __half val;
563NV_IF_ELSE_TARGET(NV_IS_DEVICE,
564 asm("{ cvt.rn.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(a));
565,
566 __half_raw r;
567 unsigned int sign = 0U;
568 unsigned int remainder = 0U;
569 r.x = __internal_float2half(a, sign, remainder);
570 if ((remainder > 0x80000000U) || ((remainder == 0x80000000U) && ((r.x & 0x1U) != 0U))) {
571 r.x++;
572 }
573 val = r;
574)
575 return val;
576}
577__CUDA_HOSTDEVICE_FP16_DECL__ __half __float2half_rz(const float a)
578{
579 __half val;
580NV_IF_ELSE_TARGET(NV_IS_DEVICE,
581 asm("{ cvt.rz.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(a));
582,
583 __half_raw r;
584 unsigned int sign = 0U;
585 unsigned int remainder = 0U;
586 r.x = __internal_float2half(a, sign, remainder);
587 val = r;
588)
589 return val;
590}
591__CUDA_HOSTDEVICE_FP16_DECL__ __half __float2half_rd(const float a)
592{
593 __half val;
594NV_IF_ELSE_TARGET(NV_IS_DEVICE,
595 asm("{ cvt.rm.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(a));
596,
597 __half_raw r;
598 unsigned int sign = 0U;
599 unsigned int remainder = 0U;
600 r.x = __internal_float2half(a, sign, remainder);
601 if ((remainder != 0U) && (sign != 0U)) {
602 r.x++;
603 }
604 val = r;
605)
606 return val;
607}
608__CUDA_HOSTDEVICE_FP16_DECL__ __half __float2half_ru(const float a)
609{
610 __half val;
611NV_IF_ELSE_TARGET(NV_IS_DEVICE,
612 asm("{ cvt.rp.f16.f32 %0, %1;}\n" : "=h"(__HALF_TO_US(val)) : "f"(a));
613,
614 __half_raw r;
615 unsigned int sign = 0U;
616 unsigned int remainder = 0U;
617 r.x = __internal_float2half(a, sign, remainder);
618 if ((remainder != 0U) && (sign == 0U)) {
619 r.x++;
620 }
621 val = r;
622)
623 return val;
624}
625__CUDA_HOSTDEVICE_FP16_DECL__ __half2 __float2half2_rn(const float a)
626{
627 __half2 val;
628NV_IF_ELSE_TARGET(NV_IS_DEVICE,
629 asm("{.reg .f16 low;\n"
630 " cvt.rn.f16.f32 low, %1;\n"
631 " mov.b32 %0, {low,low};}\n" : "=r"(__HALF2_TO_UI(val)) : "f"(a));
632,
633 val = __half2(__float2half_rn(a), __float2half_rn(a));
634)
635 return val;
636}
637
638#if defined(__CUDACC__) || defined(_NVHPC_CUDA)
639__CUDA_FP16_DECL__ __half2 __internal_device_float2_to_half2_rn(const float a, const float b) {
640 __half2 val;
641NV_IF_ELSE_TARGET(NV_PROVIDES_SM_80,
642 asm("{ cvt.rn.f16x2.f32 %0, %2, %1; }\n"
643 : "=r"(__HALF2_TO_UI(val)) : "f"(a), "f"(b));
644,
645 asm("{.reg .f16 low,high;\n"
646 " cvt.rn.f16.f32 low, %1;\n"
647 " cvt.rn.f16.f32 high, %2;\n"
648 " mov.b32 %0, {low,high};}\n" : "=r"(__HALF2_TO_UI(val)) : "f"(a), "f"(b));
649)
650 return val;
651}
652
653#endif /* defined(__CUDACC__) || defined(_NVHPC_CUDA) */
654
655__CUDA_HOSTDEVICE_FP16_DECL__ __half2 __floats2half2_rn(const float a, const float b)
656{
657 __half2 val;
658NV_IF_ELSE_TARGET(NV_IS_DEVICE,
659 val = __internal_device_float2_to_half2_rn(a,b);
660,
661 val = __half2(__float2half_rn(a), __float2half_rn(b));
662)
663 return val;
664}
665
666#ifndef __CUDACC_RTC__ /* no host functions in NVRTC mode */
667static inline float __internal_half2float(const unsigned short h)
668{
669 unsigned int sign = ((static_cast<unsigned int>(h) >> 15U) & 1U);
670 unsigned int exponent = ((static_cast<unsigned int>(h) >> 10U) & 0x1fU);
671 unsigned int mantissa = ((static_cast<unsigned int>(h) & 0x3ffU) << 13U);
672 float f;
673 if (exponent == 0x1fU) { /* NaN or Inf */
674 /* discard sign of a NaN */
675 sign = ((mantissa != 0U) ? (sign >> 1U) : sign);
676 mantissa = ((mantissa != 0U) ? 0x7fffffU : 0U);
677 exponent = 0xffU;
678 } else if (exponent == 0U) { /* Denorm or Zero */
679 if (mantissa != 0U) {
680 unsigned int msb;
681 exponent = 0x71U;
682 do {
683 msb = (mantissa & 0x400000U);
684 mantissa <<= 1U; /* normalize */
685 --exponent;
686 } while (msb == 0U);
687 mantissa &= 0x7fffffU; /* 1.mantissa is implicit */
688 }
689 } else {
690 exponent += 0x70U;
691 }
692 const unsigned int u = ((sign << 31U) | (exponent << 23U) | mantissa);
693#if defined(__CUDACC__)
694 (void)memcpy(&f, &u, sizeof(u));
695#else
696 (void)std::memcpy(&f, &u, sizeof(u));
697#endif
698 return f;
699}
700#endif /* !defined(__CUDACC_RTC__) */
701
702__CUDA_HOSTDEVICE_FP16_DECL__ float __half2float(const __half a)
703{
704 float val;
705NV_IF_ELSE_TARGET(NV_IS_DEVICE,
706 asm("{ cvt.f32.f16 %0, %1;}\n" : "=f"(val) : "h"(__HALF_TO_CUS(a)));
707,
708 val = __internal_half2float(static_cast<__half_raw>(a).x);
709)
710 return val;
711}
712__CUDA_HOSTDEVICE_FP16_DECL__ float __low2float(const __half2 a)
713{
714 float val;
715NV_IF_ELSE_TARGET(NV_IS_DEVICE,
716 asm("{.reg .f16 low,high;\n"
717 " mov.b32 {low,high},%1;\n"
718 " cvt.f32.f16 %0, low;}\n" : "=f"(val) : "r"(__HALF2_TO_CUI(a)));
719,
720 val = __internal_half2float(static_cast<__half2_raw>(a).x);
721)
722 return val;
723}
724__CUDA_HOSTDEVICE_FP16_DECL__ float __high2float(const __half2 a)
725{
726 float val;
727NV_IF_ELSE_TARGET(NV_IS_DEVICE,
728 asm("{.reg .f16 low,high;\n"
729 " mov.b32 {low,high},%1;\n"
730 " cvt.f32.f16 %0, high;}\n" : "=f"(val) : "r"(__HALF2_TO_CUI(a)));
731,
732 val = __internal_half2float(static_cast<__half2_raw>(a).y);
733)
734 return val;
735}
736
737__CUDA_HOSTDEVICE_FP16_DECL__ signed char __half2char_rz(const __half h)
738{
739 signed char i;
740NV_IF_ELSE_TARGET(NV_PROVIDES_SM_90,
741 unsigned int tmp;
742 asm("cvt.rzi.s8.f16 %0, %1;" : "=r"(tmp) : "h"(__HALF_TO_CUS(h)));
743 const unsigned char u = static_cast<unsigned char>(tmp);
744 i = static_cast<signed char>(u);
745,
746 const float f = __half2float(h);
747 const signed char max_val = (signed char)0x7fU;
748 const signed char min_val = (signed char)0x80U;
749 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
750 // saturation fixup
751 if (bits > (unsigned short)0xF800U) {
752 // NaN
753 i = 0;
754 } else if (f > static_cast<float>(max_val)) {
755 // saturate maximum
756 i = max_val;
757 } else if (f < static_cast<float>(min_val)) {
758 // saturate minimum
759 i = min_val;
760 } else {
761 // normal value, conversion is well-defined
762 i = static_cast<signed char>(f);
763 }
764)
765 return i;
766}
767
768__CUDA_HOSTDEVICE_FP16_DECL__ unsigned char __half2uchar_rz(const __half h)
769{
770 unsigned char i;
771NV_IF_ELSE_TARGET(NV_PROVIDES_SM_90,
772 unsigned int tmp;
773 asm("cvt.rzi.u8.f16 %0, %1;" : "=r"(tmp) : "h"(__HALF_TO_CUS(h)));
774 i = static_cast<unsigned char>(tmp);
775,
776 const float f = __half2float(h);
777 const unsigned char max_val = 0xffU;
778 const unsigned char min_val = 0U;
779 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
780 // saturation fixup
781 if (bits > (unsigned short)0xF800U) {
782 // NaN
783 i = 0U;
784 } else if (f > static_cast<float>(max_val)) {
785 // saturate maximum
786 i = max_val;
787 } else if (f < static_cast<float>(min_val)) {
788 // saturate minimum
789 i = min_val;
790 } else {
791 // normal value, conversion is well-defined
792 i = static_cast<unsigned char>(f);
793 }
794)
795 return i;
796}
797
798__CUDA_HOSTDEVICE_FP16_DECL__ short int __half2short_rz(const __half h)
799{
800 short int i;
801NV_IF_ELSE_TARGET(NV_IS_DEVICE,
802 asm("cvt.rzi.s16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
803,
804 const float f = __half2float(h);
805 const short int max_val = (short int)0x7fffU;
806 const short int min_val = (short int)0x8000U;
807 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
808 // saturation fixup
809 if (bits > (unsigned short)0xF800U) {
810 // NaN
811 i = 0;
812 } else if (f > static_cast<float>(max_val)) {
813 // saturate maximum
814 i = max_val;
815 } else if (f < static_cast<float>(min_val)) {
816 // saturate minimum
817 i = min_val;
818 } else {
819 // normal value, conversion is well-defined
820 i = static_cast<short int>(f);
821 }
822)
823 return i;
824}
825__CUDA_HOSTDEVICE_FP16_DECL__ unsigned short int __half2ushort_rz(const __half h)
826{
827 unsigned short int i;
828NV_IF_ELSE_TARGET(NV_IS_DEVICE,
829 asm("cvt.rzi.u16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
830,
831 const float f = __half2float(h);
832 const unsigned short int max_val = 0xffffU;
833 const unsigned short int min_val = 0U;
834 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
835 // saturation fixup
836 if (bits > (unsigned short)0xF800U) {
837 // NaN
838 i = 0U;
839 } else if (f > static_cast<float>(max_val)) {
840 // saturate maximum
841 i = max_val;
842 } else if (f < static_cast<float>(min_val)) {
843 // saturate minimum
844 i = min_val;
845 } else {
846 // normal value, conversion is well-defined
847 i = static_cast<unsigned short int>(f);
848 }
849)
850 return i;
851}
852__CUDA_HOSTDEVICE_FP16_DECL__ int __half2int_rz(const __half h)
853{
854 int i;
855NV_IF_ELSE_TARGET(NV_IS_DEVICE,
856 asm("cvt.rzi.s32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
857,
858 const float f = __half2float(h);
859 const int max_val = (int)0x7fffffffU;
860 const int min_val = (int)0x80000000U;
861 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
862 // saturation fixup
863 if (bits > (unsigned short)0xF800U) {
864 // NaN
865 i = 0;
866 } else if (f > static_cast<float>(max_val)) {
867 // saturate maximum
868 i = max_val;
869 } else if (f < static_cast<float>(min_val)) {
870 // saturate minimum
871 i = min_val;
872 } else {
873 // normal value, conversion is well-defined
874 i = static_cast<int>(f);
875 }
876)
877 return i;
878}
879__CUDA_HOSTDEVICE_FP16_DECL__ unsigned int __half2uint_rz(const __half h)
880{
881 unsigned int i;
882NV_IF_ELSE_TARGET(NV_IS_DEVICE,
883 asm("cvt.rzi.u32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
884,
885 const float f = __half2float(h);
886 const unsigned int max_val = 0xffffffffU;
887 const unsigned int min_val = 0U;
888 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
889 // saturation fixup
890 if (bits > (unsigned short)0xF800U) {
891 // NaN
892 i = 0U;
893 } else if (f > static_cast<float>(max_val)) {
894 // saturate maximum
895 i = max_val;
896 } else if (f < static_cast<float>(min_val)) {
897 // saturate minimum
898 i = min_val;
899 } else {
900 // normal value, conversion is well-defined
901 i = static_cast<unsigned int>(f);
902 }
903)
904 return i;
905}
906__CUDA_HOSTDEVICE_FP16_DECL__ long long int __half2ll_rz(const __half h)
907{
908 long long int i;
909NV_IF_ELSE_TARGET(NV_IS_DEVICE,
910 asm("cvt.rzi.s64.f16 %0, %1;" : "=l"(i) : "h"(__HALF_TO_CUS(h)));
911,
912 const float f = __half2float(h);
913 const long long int max_val = (long long int)0x7fffffffffffffffULL;
914 const long long int min_val = (long long int)0x8000000000000000ULL;
915 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
916 // saturation fixup
917 if (bits > (unsigned short)0xF800U) {
918 // NaN
919 i = min_val;
920 } else if (f > static_cast<float>(max_val)) {
921 // saturate maximum
922 i = max_val;
923 } else if (f < static_cast<float>(min_val)) {
924 // saturate minimum
925 i = min_val;
926 } else {
927 // normal value, conversion is well-defined
928 i = static_cast<long long int>(f);
929 }
930)
931 return i;
932}
933__CUDA_HOSTDEVICE_FP16_DECL__ unsigned long long int __half2ull_rz(const __half h)
934{
935 unsigned long long int i;
936NV_IF_ELSE_TARGET(NV_IS_DEVICE,
937 asm("cvt.rzi.u64.f16 %0, %1;" : "=l"(i) : "h"(__HALF_TO_CUS(h)));
938,
939 const float f = __half2float(h);
940 const unsigned long long int max_val = 0xffffffffffffffffULL;
941 const unsigned long long int min_val = 0ULL;
942 const unsigned short bits = static_cast<unsigned short>(static_cast<__half_raw>(h).x << 1U);
943 // saturation fixup
944 if (bits > (unsigned short)0xF800U) {
945 // NaN
946 i = 0x8000000000000000ULL;
947 } else if (f > static_cast<float>(max_val)) {
948 // saturate maximum
949 i = max_val;
950 } else if (f < static_cast<float>(min_val)) {
951 // saturate minimum
952 i = min_val;
953 } else {
954 // normal value, conversion is well-defined
955 i = static_cast<unsigned long long int>(f);
956 }
957)
958 return i;
959}
960/* CUDA vector-types compatible vector creation function (note returns __half2, not half2) */
961__CUDA_HOSTDEVICE_FP16_DECL__ __half2 make_half2(const __half x, const __half y)
962{
963 __half2 t; t.x = x; t.y = y; return t;
964}
965
966
967/* Definitions of intrinsics */
968__CUDA_HOSTDEVICE_FP16_DECL__ __half2 __float22half2_rn(const float2 a)
969{
970 const __half2 val = __floats2half2_rn(a.x, a.y);
971 return val;
972}
973__CUDA_HOSTDEVICE_FP16_DECL__ float2 __half22float2(const __half2 a)
974{
975 float hi_float;
976 float lo_float;
977NV_IF_ELSE_TARGET(NV_IS_DEVICE,
978 asm("{.reg .f16 low,high;\n"
979 " mov.b32 {low,high},%1;\n"
980 " cvt.f32.f16 %0, low;}\n" : "=f"(lo_float) : "r"(__HALF2_TO_CUI(a)));
981
982 asm("{.reg .f16 low,high;\n"
983 " mov.b32 {low,high},%1;\n"
984 " cvt.f32.f16 %0, high;}\n" : "=f"(hi_float) : "r"(__HALF2_TO_CUI(a)));
985,
986 lo_float = __internal_half2float(((__half2_raw)a).x);
987 hi_float = __internal_half2float(((__half2_raw)a).y);
988)
989 return make_float2(lo_float, hi_float);
990}
991#if defined(__CUDACC__) || defined(_NVHPC_CUDA)
992__CUDA_FP16_DECL__ int __half2int_rn(const __half h)
993{
994 int i;
995 asm("cvt.rni.s32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
996 return i;
997}
998__CUDA_FP16_DECL__ int __half2int_rd(const __half h)
999{
1000 int i;
1001 asm("cvt.rmi.s32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
1002 return i;
1003}
1004__CUDA_FP16_DECL__ int __half2int_ru(const __half h)
1005{
1006 int i;
1007 asm("cvt.rpi.s32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
1008 return i;
1009}
1010#endif /* defined(__CUDACC__) || defined(_NVHPC_CUDA) */
1011__CUDA_HOSTDEVICE_FP16_DECL__ __half __int2half_rn(const int i)
1012{
1013 __half h;
1014NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1015 asm("cvt.rn.f16.s32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1016,
1017 // double-rounding is not a problem here: if integer
1018 // has more than 24 bits, it is already too large to
1019 // be represented in half precision, and result will
1020 // be infinity.
1021 const float f = static_cast<float>(i);
1022 h = __float2half_rn(f);
1023)
1024 return h;
1025}
1026__CUDA_HOSTDEVICE_FP16_DECL__ __half __int2half_rz(const int i)
1027{
1028 __half h;
1029NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1030 asm("cvt.rz.f16.s32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1031,
1032 const float f = static_cast<float>(i);
1033 h = __float2half_rz(f);
1034)
1035 return h;
1036}
1037__CUDA_HOSTDEVICE_FP16_DECL__ __half __int2half_rd(const int i)
1038{
1039 __half h;
1040NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1041 asm("cvt.rm.f16.s32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1042,
1043 const float f = static_cast<float>(i);
1044 h = __float2half_rd(f);
1045)
1046 return h;
1047}
1048__CUDA_HOSTDEVICE_FP16_DECL__ __half __int2half_ru(const int i)
1049{
1050 __half h;
1051NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1052 asm("cvt.rp.f16.s32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1053,
1054 const float f = static_cast<float>(i);
1055 h = __float2half_ru(f);
1056)
1057 return h;
1058}
1059#if defined(__CUDACC__) || defined(_NVHPC_CUDA)
1060__CUDA_FP16_DECL__ short int __half2short_rn(const __half h)
1061{
1062 short int i;
1063 asm("cvt.rni.s16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
1064 return i;
1065}
1066__CUDA_FP16_DECL__ short int __half2short_rd(const __half h)
1067{
1068 short int i;
1069 asm("cvt.rmi.s16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
1070 return i;
1071}
1072__CUDA_FP16_DECL__ short int __half2short_ru(const __half h)
1073{
1074 short int i;
1075 asm("cvt.rpi.s16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
1076 return i;
1077}
1078#endif /* defined(__CUDACC__) || defined(_NVHPC_CUDA) */
1079__CUDA_HOSTDEVICE_FP16_DECL__ __half __short2half_rn(const short int i)
1080{
1081 __half h;
1082NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1083 asm("cvt.rn.f16.s16 %0, %1;" : "=h"(__HALF_TO_US(h)) : "h"(i));
1084,
1085 const float f = static_cast<float>(i);
1086 h = __float2half_rn(f);
1087)
1088 return h;
1089}
1090__CUDA_HOSTDEVICE_FP16_DECL__ __half __short2half_rz(const short int i)
1091{
1092 __half h;
1093NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1094 asm("cvt.rz.f16.s16 %0, %1;" : "=h"(__HALF_TO_US(h)) : "h"(i));
1095,
1096 const float f = static_cast<float>(i);
1097 h = __float2half_rz(f);
1098)
1099 return h;
1100}
1101__CUDA_HOSTDEVICE_FP16_DECL__ __half __short2half_rd(const short int i)
1102{
1103 __half h;
1104NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1105 asm("cvt.rm.f16.s16 %0, %1;" : "=h"(__HALF_TO_US(h)) : "h"(i));
1106,
1107 const float f = static_cast<float>(i);
1108 h = __float2half_rd(f);
1109)
1110 return h;
1111}
1112__CUDA_HOSTDEVICE_FP16_DECL__ __half __short2half_ru(const short int i)
1113{
1114 __half h;
1115NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1116 asm("cvt.rp.f16.s16 %0, %1;" : "=h"(__HALF_TO_US(h)) : "h"(i));
1117,
1118 const float f = static_cast<float>(i);
1119 h = __float2half_ru(f);
1120)
1121 return h;
1122}
1123#if defined(__CUDACC__) || defined(_NVHPC_CUDA)
1124__CUDA_FP16_DECL__ unsigned int __half2uint_rn(const __half h)
1125{
1126 unsigned int i;
1127 asm("cvt.rni.u32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
1128 return i;
1129}
1130__CUDA_FP16_DECL__ unsigned int __half2uint_rd(const __half h)
1131{
1132 unsigned int i;
1133 asm("cvt.rmi.u32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
1134 return i;
1135}
1136__CUDA_FP16_DECL__ unsigned int __half2uint_ru(const __half h)
1137{
1138 unsigned int i;
1139 asm("cvt.rpi.u32.f16 %0, %1;" : "=r"(i) : "h"(__HALF_TO_CUS(h)));
1140 return i;
1141}
1142#endif /* defined(__CUDACC__) || defined(_NVHPC_CUDA) */
1143__CUDA_HOSTDEVICE_FP16_DECL__ __half __uint2half_rn(const unsigned int i)
1144{
1145 __half h;
1146NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1147 asm("cvt.rn.f16.u32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1148,
1149 // double-rounding is not a problem here: if integer
1150 // has more than 24 bits, it is already too large to
1151 // be represented in half precision, and result will
1152 // be infinity.
1153 const float f = static_cast<float>(i);
1154 h = __float2half_rn(f);
1155)
1156 return h;
1157}
1158__CUDA_HOSTDEVICE_FP16_DECL__ __half __uint2half_rz(const unsigned int i)
1159{
1160 __half h;
1161NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1162 asm("cvt.rz.f16.u32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1163,
1164 const float f = static_cast<float>(i);
1165 h = __float2half_rz(f);
1166)
1167 return h;
1168}
1169__CUDA_HOSTDEVICE_FP16_DECL__ __half __uint2half_rd(const unsigned int i)
1170{
1171 __half h;
1172NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1173 asm("cvt.rm.f16.u32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1174,
1175 const float f = static_cast<float>(i);
1176 h = __float2half_rd(f);
1177)
1178 return h;
1179}
1180__CUDA_HOSTDEVICE_FP16_DECL__ __half __uint2half_ru(const unsigned int i)
1181{
1182 __half h;
1183NV_IF_ELSE_TARGET(NV_IS_DEVICE,
1184 asm("cvt.rp.f16.u32 %0, %1;" : "=h"(__HALF_TO_US(h)) : "r"(i));
1185,
1186 const float f = static_cast<float>(i);
1187 h = __float2half_ru(f);
1188)
1189 return h;
1190}
1191#if defined(__CUDACC__) || defined(_NVHPC_CUDA)
1192__CUDA_FP16_DECL__ unsigned short int __half2ushort_rn(const __half h)
1193{
1194 unsigned short int i;
1195 asm("cvt.rni.u16.f16 %0, %1;" : "=h"(i) : "h"(__HALF_TO_CUS(h)));
1196 return i;
1197}
1198__CUDA_FP16_DECL__ unsigned short int __half2ushort_rd(const __half h)
1199{
1200 unsigned short int i;
