DPC++ Runtime
Runtime libraries for oneAPI DPC++
half_type.hpp
Go to the documentation of this file.
1 //==-------------- half_type.hpp --- SYCL half type ------------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <sycl/bit_cast.hpp> // for bit_cast
12 #include <sycl/detail/export.hpp> // for __SYCL_EXPORT
13 #include <sycl/detail/iostream_proxy.hpp> // for istream, ostream
14 #include <sycl/detail/vector_traits.hpp> // for vector_alignment
15 
16 #ifdef __SYCL_DEVICE_ONLY__
17 #include <sycl/aspects.hpp>
18 #endif
19 
20 #include <cstddef> // for size_t
21 #include <cstdint> // for uint16_t, uint32_t, uint8_t
22 #include <functional> // for hash
23 #include <limits> // for float_denorm_style, float_r...
24 #include <string_view> // for hash
25 #include <type_traits> // for enable_if_t
26 
27 #if !defined(__has_builtin) || !__has_builtin(__builtin_expect)
28 #define __builtin_expect(a, b) (a)
29 #endif
30 
31 #ifdef __SYCL_DEVICE_ONLY__
32 // `constexpr` could work because the implicit conversion from `float` to
33 // `_Float16` can be `constexpr`.
34 #define __SYCL_CONSTEXPR_HALF constexpr
35 #elif __cpp_lib_bit_cast || \
36  (defined(__has_builtin) && __has_builtin(__builtin_bit_cast))
37 #define __SYCL_CONSTEXPR_HALF constexpr
38 #else
39 #define __SYCL_CONSTEXPR_HALF
40 #endif
41 
42 namespace sycl {
43 inline namespace _V1 {
44 namespace detail::half_impl {
45 class half;
46 }
48 
49 namespace ext::intel::esimd::detail {
50 class WrapperElementTypeProxy;
51 } // namespace ext::intel::esimd::detail
52 
53 namespace detail {
54 
55 inline __SYCL_CONSTEXPR_HALF uint16_t float2Half(const float &Val) {
56  const uint32_t Bits = sycl::bit_cast<uint32_t>(Val);
57 
58  // Extract the sign from the float value
59  const uint16_t Sign = (Bits & 0x80000000) >> 16;
60  // Extract the fraction from the float value
61  const uint32_t Frac32 = Bits & 0x7fffff;
62  // Extract the exponent from the float value
63  const uint8_t Exp32 = (Bits & 0x7f800000) >> 23;
64  const int16_t Exp32Diff = Exp32 - 127;
65 
66  // initialize to 0, covers the case for 0 and small numbers
67  uint16_t Exp16 = 0, Frac16 = 0;
68 
69  if (__builtin_expect(Exp32Diff > 15, 0)) {
70  // Infinity and big numbers convert to infinity
71  Exp16 = 0x1f;
72  } else if (__builtin_expect(Exp32Diff > -14, 0)) {
73  // normal range for half type
74  Exp16 = Exp32Diff + 15;
75  // convert 23-bit mantissa to 10-bit mantissa.
76  Frac16 = Frac32 >> 13;
77  // Round the mantissa as given in OpenCL spec section : 6.1.1.1 The half
78  // data type.
79  // Round to nearest.
80  uint32_t roundBits = Frac32 & 0x1fff;
81  uint32_t halfway = 0x1000;
82  if (roundBits > halfway)
83  Frac16 += 1;
84  // Tie to even.
85  else if (roundBits == halfway)
86  Frac16 += Frac16 & 1;
87  } else if (__builtin_expect(Exp32Diff > -25, 0)) {
88  // subnormals
89  Frac16 = (Frac32 | (uint32_t(1) << 23)) >> (-Exp32Diff - 1);
90  }
91 
92  if (__builtin_expect(Exp32 == 0xff && Frac32 != 0, 0)) {
93  // corner case: FP32 is NaN
94  Exp16 = 0x1F;
95  Frac16 = 0x200;
96  }
97 
98  // Compose the final FP16 binary
99  uint16_t Ret = 0;
100  Ret |= Sign;
101  Ret |= Exp16 << 10;
102  Ret += Frac16; // Add the carry bit from operation Frac16 += 1;
103 
104  return Ret;
105 }
106 
107 inline __SYCL_CONSTEXPR_HALF float half2Float(const uint16_t &Val) {
108  // Extract the sign from the bits. It is 1 if the sign is negative
109  const uint32_t Sign = static_cast<uint32_t>(Val & 0x8000) << 16;
110  // Extract the exponent from the bits
111  const uint8_t Exp16 = (Val & 0x7c00) >> 10;
112  // Extract the fraction from the bits
113  uint16_t Frac16 = Val & 0x3ff;
114 
115  uint32_t Exp32 = 0;
116  if (__builtin_expect(Exp16 == 0x1f, 0)) {
117  Exp32 = 0xff;
118  } else if (__builtin_expect(Exp16 == 0, 0)) {
119  Exp32 = 0;
120  } else {
121  Exp32 = static_cast<uint32_t>(Exp16) + 112;
122  }
123  // corner case: subnormal -> normal
124  // The denormal number of FP16 can be represented by FP32, therefore we need
125  // to recover the exponent and recalculate the fration.
126  if (__builtin_expect(Exp16 == 0 && Frac16 != 0, 0)) {
127  uint8_t OffSet = 0;
128  do {
129  ++OffSet;
130  Frac16 <<= 1;
131  } while ((Frac16 & 0x400) != 0x400);
132  // mask the 9th bit
133  Frac16 &= 0x3ff;
134  Exp32 = 113 - OffSet;
135  }
136 
137  uint32_t Frac32 = Frac16 << 13;
138 
139  uint32_t Bits = 0;
140  Bits |= Sign;
141  Bits |= (Exp32 << 23);
142  Bits |= Frac32;
143  const float Result = sycl::bit_cast<float>(Bits);
144  return Result;
145 }
146 
147 namespace half_impl {
148 class half;
149 
150 // Several aliases are defined below:
151 // - StorageT: actual representation of half data type. It is used by scalar
152 // half values. On device side, it points to some native half data type, while
153 // on host it is represented by a 16-bit integer that the implementation
154 // manipulates to emulate half-precision floating-point behavior.
155 //
156 // - BIsRepresentationT: data type which is used by built-in functions. It is
157 // distinguished from StorageT, because on host, we can still operate on the
158 // wrapper itself and there is no sense in direct usage of underlying data
159 // type (too many changes required for BIs implementation without any
160 // foreseeable profits)
161 //
162 // - VecElemT: representation of each element in the vector. On device it is
163 // the same as StorageT to carry a native vector representation, while on
164 // host it stores the sycl::half implementation directly.
165 //
166 // - VecNStorageT: representation of N-element vector of halfs. Follows the
167 // same logic as VecElemT.
168 #ifdef __SYCL_DEVICE_ONLY__
169 using StorageT = _Float16;
170 using BIsRepresentationT = _Float16;
171 using VecElemT = _Float16;
172 #else // SYCL_DEVICE_ONLY
173 using StorageT = uint16_t;
174 // No need to extract underlying data type for built-in functions operating on
175 // host
177 using VecElemT = half;
178 #endif // SYCL_DEVICE_ONLY
179 
180 // Creation token to disambiguate constructors.
182  constexpr explicit RawHostHalfToken(uint16_t Val) : Value{Val} {}
183  uint16_t Value;
184 };
185 
186 #ifndef __SYCL_DEVICE_ONLY__
187 class half {
188 #else
189 class [[__sycl_detail__::__uses_aspects__(aspect::fp16)]] half {
190 #endif
191 public:
192  half() = default;
193  constexpr half(const half &) = default;
194  constexpr half(half &&) = default;
195 
196 #ifdef __SYCL_DEVICE_ONLY__
197  __SYCL_CONSTEXPR_HALF half(const float &rhs) : Data(rhs) {}
198 #else
199  __SYCL_CONSTEXPR_HALF half(const float &rhs) : Data(float2Half(rhs)) {}
200 #endif // __SYCL_DEVICE_ONLY__
201 
202  constexpr half &operator=(const half &rhs) = default;
203 
204  // Operator +=, -=, *=, /=
205 #ifdef __SYCL_DEVICE_ONLY__
207  Data += rhs.Data;
208  return *this;
209  }
210 
212  Data -= rhs.Data;
213  return *this;
214  }
215 
217  Data *= rhs.Data;
218  return *this;
219  }
220 
222  Data /= rhs.Data;
223  return *this;
224  }
225 #else
227  *this = operator float() + static_cast<float>(rhs);
228  return *this;
229  }
230 
232  *this = operator float() - static_cast<float>(rhs);
233  return *this;
234  }
235 
237  *this = operator float() * static_cast<float>(rhs);
238  return *this;
239  }
240 
242  *this = operator float() / static_cast<float>(rhs);
243  return *this;
244  }
245 #endif // __SYCL_DEVICE_ONLY__
246 
247  // Operator ++, --
249  *this += 1;
250  return *this;
251  }
252 
254  half ret(*this);
255  operator++();
256  return ret;
257  }
258 
260  *this -= 1;
261  return *this;
262  }
263 
265  half ret(*this);
266  operator--();
267  return ret;
268  }
269 
270  // Operator neg
271 #ifdef __SYCL_DEVICE_ONLY__
272  __SYCL_CONSTEXPR_HALF friend half operator-(const half other) {
273  return half(-other.Data);
274  }
275 #else
276  __SYCL_CONSTEXPR_HALF friend half operator-(const half other) {
277  return half(RawHostHalfToken(other.Data ^ 0x8000));
278  }
279 #endif // __SYCL_DEVICE_ONLY__
280 
281 // Operator +, -, *, /
282 #define OP(op, op_eq) \
283  __SYCL_CONSTEXPR_HALF friend half operator op(const half lhs, \
284  const half rhs) { \
285  half rtn = lhs; \
286  rtn op_eq rhs; \
287  return rtn; \
288  } \
289  __SYCL_CONSTEXPR_HALF friend double operator op(const half lhs, \
290  const double rhs) { \
291  double rtn = lhs; \
292  rtn op_eq rhs; \
293  return rtn; \
294  } \
295  __SYCL_CONSTEXPR_HALF friend double operator op(const double lhs, \
296  const half rhs) { \
297  double rtn = lhs; \
298  rtn op_eq rhs; \
299  return rtn; \
300  } \
301  __SYCL_CONSTEXPR_HALF friend float operator op(const half lhs, \
302  const float rhs) { \
303  float rtn = lhs; \
304  rtn op_eq rhs; \
305  return rtn; \
306  } \
307  __SYCL_CONSTEXPR_HALF friend float operator op(const float lhs, \
308  const half rhs) { \
309  float rtn = lhs; \
310  rtn op_eq rhs; \
311  return rtn; \
312  } \
313  __SYCL_CONSTEXPR_HALF friend half operator op(const half lhs, \
314  const int rhs) { \
315  half rtn = lhs; \
316  rtn op_eq rhs; \
317  return rtn; \
318  } \
319  __SYCL_CONSTEXPR_HALF friend half operator op(const int lhs, \
320  const half rhs) { \
321  half rtn = lhs; \
322  rtn op_eq rhs; \
323  return rtn; \
324  } \
325  __SYCL_CONSTEXPR_HALF friend half operator op(const half lhs, \
326  const long rhs) { \
327  half rtn = lhs; \
328  rtn op_eq rhs; \
329  return rtn; \
330  } \
331  __SYCL_CONSTEXPR_HALF friend half operator op(const long lhs, \
332  const half rhs) { \
333  half rtn = lhs; \
334  rtn op_eq rhs; \
335  return rtn; \
336  } \
337  __SYCL_CONSTEXPR_HALF friend half operator op(const half lhs, \
338  const long long rhs) { \
339  half rtn = lhs; \
340  rtn op_eq rhs; \
341  return rtn; \
342  } \
343  __SYCL_CONSTEXPR_HALF friend half operator op(const long long lhs, \
344  const half rhs) { \
345  half rtn = lhs; \
346  rtn op_eq rhs; \
347  return rtn; \
348  } \
349  __SYCL_CONSTEXPR_HALF friend half operator op(const half &lhs, \
350  const unsigned int &rhs) { \
351  half rtn = lhs; \
352  rtn op_eq rhs; \
353  return rtn; \
354  } \
355  __SYCL_CONSTEXPR_HALF friend half operator op(const unsigned int &lhs, \
356  const half &rhs) { \
357  half rtn = lhs; \
358  rtn op_eq rhs; \
359  return rtn; \
360  } \
361  __SYCL_CONSTEXPR_HALF friend half operator op(const half &lhs, \
362  const unsigned long &rhs) { \
363  half rtn = lhs; \
364  rtn op_eq rhs; \
365  return rtn; \
366  } \
367  __SYCL_CONSTEXPR_HALF friend half operator op(const unsigned long &lhs, \
368  const half &rhs) { \
369  half rtn = lhs; \
370  rtn op_eq rhs; \
371  return rtn; \
372  } \
373  __SYCL_CONSTEXPR_HALF friend half operator op( \
374  const half &lhs, const unsigned long long &rhs) { \
375  half rtn = lhs; \
376  rtn op_eq rhs; \
377  return rtn; \
378  } \
379  __SYCL_CONSTEXPR_HALF friend half operator op(const unsigned long long &lhs, \
380  const half &rhs) { \
381  half rtn = lhs; \
382  rtn op_eq rhs; \
383  return rtn; \
384  }
385  OP(+, +=)
386  OP(-, -=)
387  OP(*, *=)
388  OP(/, /=)
389 
390 #undef OP
391 
392 // Operator ==, !=, <, >, <=, >=
393 #define OP(op) \
394  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
395  const half &rhs) { \
396  return lhs.getFPRep() op rhs.getFPRep(); \
397  } \
398  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
399  const double &rhs) { \
400  return lhs.getFPRep() op rhs; \
401  } \
402  __SYCL_CONSTEXPR_HALF friend bool operator op(const double &lhs, \
403  const half &rhs) { \
404  return lhs op rhs.getFPRep(); \
405  } \
406  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
407  const float &rhs) { \
408  return lhs.getFPRep() op rhs; \
409  } \
410  __SYCL_CONSTEXPR_HALF friend bool operator op(const float &lhs, \
411  const half &rhs) { \
412  return lhs op rhs.getFPRep(); \
413  } \
414  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
415  const int &rhs) { \
416  return lhs.getFPRep() op rhs; \
417  } \
418  __SYCL_CONSTEXPR_HALF friend bool operator op(const int &lhs, \
419  const half &rhs) { \
420  return lhs op rhs.getFPRep(); \
421  } \
422  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
423  const long &rhs) { \
424  return lhs.getFPRep() op rhs; \
425  } \
426  __SYCL_CONSTEXPR_HALF friend bool operator op(const long &lhs, \
427  const half &rhs) { \
428  return lhs op rhs.getFPRep(); \
429  } \
430  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
431  const long long &rhs) { \
432  return lhs.getFPRep() op rhs; \
433  } \
434  __SYCL_CONSTEXPR_HALF friend bool operator op(const long long &lhs, \
435  const half &rhs) { \
436  return lhs op rhs.getFPRep(); \
437  } \
438  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
439  const unsigned int &rhs) { \
440  return lhs.getFPRep() op rhs; \
441  } \
442  __SYCL_CONSTEXPR_HALF friend bool operator op(const unsigned int &lhs, \
443  const half &rhs) { \
444  return lhs op rhs.getFPRep(); \
445  } \
446  __SYCL_CONSTEXPR_HALF friend bool operator op(const half &lhs, \
447  const unsigned long &rhs) { \
448  return lhs.getFPRep() op rhs; \
449  } \
450  __SYCL_CONSTEXPR_HALF friend bool operator op(const unsigned long &lhs, \
451  const half &rhs) { \
452  return lhs op rhs.getFPRep(); \
453  } \
454  __SYCL_CONSTEXPR_HALF friend bool operator op( \
455  const half &lhs, const unsigned long long &rhs) { \
456  return lhs.getFPRep() op rhs; \
457  } \
458  __SYCL_CONSTEXPR_HALF friend bool operator op(const unsigned long long &lhs, \
459  const half &rhs) { \
460  return lhs op rhs.getFPRep(); \
461  }
462  OP(==)
463  OP(!=)
464  OP(<)
465  OP(>)
466  OP(<=)
467  OP(>=)
468 
469 #undef OP
470 
471  // Operator float
472 #ifdef __SYCL_DEVICE_ONLY__
473  __SYCL_CONSTEXPR_HALF operator float() const {
474  return static_cast<float>(Data);
475  }
476 #else
477  __SYCL_CONSTEXPR_HALF operator float() const { return half2Float(Data); }
478 #endif // __SYCL_DEVICE_ONLY__
479 
480  // Operator << and >>
481  inline friend std::ostream &operator<<(std::ostream &O,
482  sycl::half const &rhs) {
483  O << static_cast<float>(rhs);
484  return O;
485  }
486 
487  inline friend std::istream &operator>>(std::istream &I, sycl::half &rhs) {
488  float ValFloat = 0.0f;
489  I >> ValFloat;
490  rhs = ValFloat;
491  return I;
492  }
493 
494  template <typename Key> friend struct std::hash;
495 
496  friend class sycl::ext::intel::esimd::detail::WrapperElementTypeProxy;
497 
498 private:
499  // When doing operations, we cannot simply work with Data on host as
500  // it is an integer. Instead, convert it to float. On device we can work with
501  // Data as it is already a floating point representation.
502 #ifdef __SYCL_DEVICE_ONLY__
503  __SYCL_CONSTEXPR_HALF StorageT getFPRep() const { return Data; }
504 #else
505  __SYCL_CONSTEXPR_HALF float getFPRep() const { return operator float(); }
506 #endif
507 
508 #ifndef __SYCL_DEVICE_ONLY__
509  // Because sycl::bit_cast might not be constexpr on certain systems,
510  // implementation needs shortcut for creating a host sycl::half directly from
511  // a uint16_t representation.
512  constexpr explicit half(RawHostHalfToken X) : Data(X.Value) {}
513 
514  friend constexpr inline half CreateHostHalfRaw(uint16_t X);
515 #endif // __SYCL_DEVICE_ONLY__
516 
517  StorageT Data;
518 };
519 
520 #ifndef __SYCL_DEVICE_ONLY__
521 constexpr inline half CreateHostHalfRaw(uint16_t X) {
522  return half(RawHostHalfToken(X));
523 }
524 #endif // __SYCL_DEVICE_ONLY__
525 } // namespace half_impl
526 
527 // According to the C++ standard, math functions from cmath/math.h should work
528 // only on arithmetic types. We can't specify half type as arithmetic/floating
529 // point(via std::is_floating_point) since only float, double and long double
530 // types are "floating point" according to the standard. In order to use half
531 // type with these math functions we cast half to float using template
532 // function helper.
533 template <typename T> inline T cast_if_host_half(T val) { return val; }
534 
536  return static_cast<float>(val);
537 }
538 
539 } // namespace detail
540 
541 } // namespace _V1
542 } // namespace sycl
543 
544 // Partial specialization of some functions in namespace `std`
545 namespace std {
546 
547 // Partial specialization of `std::hash<sycl::half>`
548 template <> struct hash<sycl::half> {
549  size_t operator()(sycl::half const &Key) const noexcept {
550  return hash<uint16_t>{}(reinterpret_cast<const uint16_t &>(Key));
551  }
552 };
553 
554 // Partial specialization of `std::numeric<sycl::half>`
555 template <> struct numeric_limits<sycl::half> {
556  // All following values are either calculated based on description of each
557  // function/value on https://en.cppreference.com/w/cpp/types/numeric_limits,
558  // or cl_platform.h.
559  static constexpr bool is_specialized = true;
560  static constexpr bool is_signed = true;
561  static constexpr bool is_integer = false;
562  static constexpr bool is_exact = false;
563  static constexpr bool has_infinity = true;
564  static constexpr bool has_quiet_NaN = true;
565  static constexpr bool has_signaling_NaN = true;
566  static constexpr float_denorm_style has_denorm = denorm_present;
567  static constexpr bool has_denorm_loss = false;
568  static constexpr bool tinyness_before = false;
569  static constexpr bool traps = false;
570  static constexpr int max_exponent10 = 4;
571  static constexpr int max_exponent = 16;
572  static constexpr int min_exponent10 = -4;
573  static constexpr int min_exponent = -13;
574  static constexpr int radix = 2;
575  static constexpr int max_digits10 = 5;
576  static constexpr int digits = 11;
577  static constexpr bool is_bounded = true;
578  static constexpr int digits10 = 3;
579  static constexpr bool is_modulo = false;
580  static constexpr bool is_iec559 = true;
581  static constexpr float_round_style round_style = round_to_nearest;
582 
584  return 6.103515625e-05f; // half minimum value
585  }
586 
588  return 65504.0f; // half maximum value
589  }
590 
592  return -65504.0f; // -1*(half maximum value)
593  }
594 
596  return 9.765625e-04f; // half epsilon
597  }
598 
600  return 0.5f;
601  }
602 
603  static constexpr const sycl::half infinity() noexcept {
604 #ifdef __SYCL_DEVICE_ONLY__
605  return __builtin_huge_valf();
606 #else
608  static_cast<uint16_t>(0x7C00));
609 #endif
610  }
611 
613  return __builtin_nanf("");
614  }
615 
617  return __builtin_nansf("");
618  }
619 
621  return 5.96046e-08f;
622  }
623 };
624 
625 } // namespace std
626 
627 #undef __SYCL_CONSTEXPR_HALF
628 #undef _CPP14_CONSTEXPR
friend std::istream & operator>>(std::istream &I, sycl::half &rhs)
Definition: half_type.hpp:487
__SYCL_CONSTEXPR_HALF half & operator/=(const half &rhs)
Definition: half_type.hpp:241
__SYCL_CONSTEXPR_HALF half & operator+=(const half &rhs)
Definition: half_type.hpp:226
__SYCL_CONSTEXPR_HALF half & operator-=(const half &rhs)
Definition: half_type.hpp:231
__SYCL_CONSTEXPR_HALF half operator--(int)
Definition: half_type.hpp:264
__SYCL_CONSTEXPR_HALF half & operator*=(const half &rhs)
Definition: half_type.hpp:236
__SYCL_CONSTEXPR_HALF friend half operator-(const half other)
Definition: half_type.hpp:276
constexpr friend half CreateHostHalfRaw(uint16_t X)
Definition: half_type.hpp:521
constexpr half(half &&)=default
constexpr half(const half &)=default
constexpr half & operator=(const half &rhs)=default
__SYCL_CONSTEXPR_HALF half & operator--()
Definition: half_type.hpp:259
__SYCL_CONSTEXPR_HALF half(const float &rhs)
Definition: half_type.hpp:199
friend std::ostream & operator<<(std::ostream &O, sycl::half const &rhs)
Definition: half_type.hpp:481
__SYCL_CONSTEXPR_HALF half & operator++()
Definition: half_type.hpp:248
__SYCL_CONSTEXPR_HALF half operator++(int)
Definition: half_type.hpp:253
#define __builtin_expect(a, b)
Definition: half_type.hpp:28
#define OP(op, op_eq)
Definition: half_type.hpp:393
#define __SYCL_CONSTEXPR_HALF
Definition: half_type.hpp:39
constexpr half CreateHostHalfRaw(uint16_t X)
Definition: half_type.hpp:521
T cast_if_host_half(T val)
Definition: half_type.hpp:533
__SYCL_CONSTEXPR_HALF uint16_t float2Half(const float &Val)
Definition: half_type.hpp:55
__SYCL_CONSTEXPR_HALF float half2Float(const uint16_t &Val)
Definition: half_type.hpp:107
sycl::detail::half_impl::half half
Definition: aliases.hpp:101
Definition: access.hpp:18
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
size_t operator()(sycl::half const &Key) const noexcept
Definition: half_type.hpp:549
static constexpr const sycl::half infinity() noexcept
Definition: half_type.hpp:603
static __SYCL_CONSTEXPR_HALF const sycl::half round_error() noexcept
Definition: half_type.hpp:599
static __SYCL_CONSTEXPR_HALF const sycl::half quiet_NaN() noexcept
Definition: half_type.hpp:612
static __SYCL_CONSTEXPR_HALF const sycl::half lowest() noexcept
Definition: half_type.hpp:591
static __SYCL_CONSTEXPR_HALF const sycl::half denorm_min() noexcept
Definition: half_type.hpp:620
static __SYCL_CONSTEXPR_HALF const sycl::half epsilon() noexcept
Definition: half_type.hpp:595
static __SYCL_CONSTEXPR_HALF const sycl::half signaling_NaN() noexcept
Definition: half_type.hpp:616