Qrack  9.0
General classical-emulating-quantum development framework
half.hpp
Go to the documentation of this file.
1 // half - IEEE 754-based half-precision floating-point library.
2 //
3 // Copyright (c) 2012-2021 Christian Rau <rauy@users.sourceforge.net>
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 // documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11 // Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 
18 // Version 2.2.0
19 
22 
23 #ifndef HALF_HALF_HPP
24 #define HALF_HALF_HPP
25 
26 #define HALF_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
27 
28 #if defined(__INTEL_COMPILER)
29 #define HALF_ICC_VERSION __INTEL_COMPILER
30 #elif defined(__ICC)
31 #define HALF_ICC_VERSION __ICC
32 #elif defined(__ICL)
33 #define HALF_ICC_VERSION __ICL
34 #else
35 #define HALF_ICC_VERSION 0
36 #endif
37 
38 // check C++11 language features
39 #if defined(__clang__) // clang
40 #if __has_feature(cxx_static_assert) && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
41 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
42 #endif
43 #if __has_feature(cxx_constexpr) && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
44 #define HALF_ENABLE_CPP11_CONSTEXPR 1
45 #endif
46 #if __has_feature(cxx_noexcept) && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
47 #define HALF_ENABLE_CPP11_NOEXCEPT 1
48 #endif
49 #if __has_feature(cxx_user_literals) && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
50 #define HALF_ENABLE_CPP11_USER_LITERALS 1
51 #endif
52 #if __has_feature(cxx_thread_local) && !defined(HALF_ENABLE_CPP11_THREAD_LOCAL)
53 #define HALF_ENABLE_CPP11_THREAD_LOCAL 1
54 #endif
55 #if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && !defined(HALF_ENABLE_CPP11_LONG_LONG)
56 #define HALF_ENABLE_CPP11_LONG_LONG 1
57 #endif
58 #elif HALF_ICC_VERSION && defined(__INTEL_CXX11_MODE__) // Intel C++
59 #if HALF_ICC_VERSION >= 1500 && !defined(HALF_ENABLE_CPP11_THREAD_LOCAL)
60 #define HALF_ENABLE_CPP11_THREAD_LOCAL 1
61 #endif
62 #if HALF_ICC_VERSION >= 1500 && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
63 #define HALF_ENABLE_CPP11_USER_LITERALS 1
64 #endif
65 #if HALF_ICC_VERSION >= 1400 && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
66 #define HALF_ENABLE_CPP11_CONSTEXPR 1
67 #endif
68 #if HALF_ICC_VERSION >= 1400 && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
69 #define HALF_ENABLE_CPP11_NOEXCEPT 1
70 #endif
71 #if HALF_ICC_VERSION >= 1110 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
72 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
73 #endif
74 #if HALF_ICC_VERSION >= 1110 && !defined(HALF_ENABLE_CPP11_LONG_LONG)
75 #define HALF_ENABLE_CPP11_LONG_LONG 1
76 #endif
77 #elif defined(__GNUC__) // gcc
78 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
79 #if HALF_GCC_VERSION >= 408 && !defined(HALF_ENABLE_CPP11_THREAD_LOCAL)
80 #define HALF_ENABLE_CPP11_THREAD_LOCAL 1
81 #endif
82 #if HALF_GCC_VERSION >= 407 && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
83 #define HALF_ENABLE_CPP11_USER_LITERALS 1
84 #endif
85 #if HALF_GCC_VERSION >= 406 && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
86 #define HALF_ENABLE_CPP11_CONSTEXPR 1
87 #endif
88 #if HALF_GCC_VERSION >= 406 && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
89 #define HALF_ENABLE_CPP11_NOEXCEPT 1
90 #endif
91 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
92 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
93 #endif
94 #if !defined(HALF_ENABLE_CPP11_LONG_LONG)
95 #define HALF_ENABLE_CPP11_LONG_LONG 1
96 #endif
97 #endif
98 #define HALF_TWOS_COMPLEMENT_INT 1
99 #elif defined(_MSC_VER) // Visual C++
100 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_THREAD_LOCAL)
101 #define HALF_ENABLE_CPP11_THREAD_LOCAL 1
102 #endif
103 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
104 #define HALF_ENABLE_CPP11_USER_LITERALS 1
105 #endif
106 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
107 #define HALF_ENABLE_CPP11_CONSTEXPR 1
108 #endif
109 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
110 #define HALF_ENABLE_CPP11_NOEXCEPT 1
111 #endif
112 #if _MSC_VER >= 1600 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
113 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
114 #endif
115 #if _MSC_VER >= 1310 && !defined(HALF_ENABLE_CPP11_LONG_LONG)
116 #define HALF_ENABLE_CPP11_LONG_LONG 1
117 #endif
118 #define HALF_TWOS_COMPLEMENT_INT 1
119 #define HALF_POP_WARNINGS 1
120 #pragma warning(push)
121 #pragma warning(disable : 4099 4127 4146) // struct vs class, constant in if, negative unsigned
122 #endif
123 
124 // check C++11 library features
125 #include <utility>
126 #if defined(_LIBCPP_VERSION) // libc++
127 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103
128 #ifndef HALF_ENABLE_CPP11_TYPE_TRAITS
129 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
130 #endif
131 #ifndef HALF_ENABLE_CPP11_CSTDINT
132 #define HALF_ENABLE_CPP11_CSTDINT 1
133 #endif
134 #ifndef HALF_ENABLE_CPP11_CMATH
135 #define HALF_ENABLE_CPP11_CMATH 1
136 #endif
137 #ifndef HALF_ENABLE_CPP11_HASH
138 #define HALF_ENABLE_CPP11_HASH 1
139 #endif
140 #ifndef HALF_ENABLE_CPP11_CFENV
141 #define HALF_ENABLE_CPP11_CFENV 1
142 #endif
143 #endif
144 #elif defined(__GLIBCXX__) // libstdc++
145 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103
146 #ifdef __clang__
147 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_TYPE_TRAITS)
148 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
149 #endif
150 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_CSTDINT)
151 #define HALF_ENABLE_CPP11_CSTDINT 1
152 #endif
153 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_CMATH)
154 #define HALF_ENABLE_CPP11_CMATH 1
155 #endif
156 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_HASH)
157 #define HALF_ENABLE_CPP11_HASH 1
158 #endif
159 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_CFENV)
160 #define HALF_ENABLE_CPP11_CFENV 1
161 #endif
162 #else
163 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_TYPE_TRAITS)
164 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
165 #endif
166 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_CSTDINT)
167 #define HALF_ENABLE_CPP11_CSTDINT 1
168 #endif
169 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_CMATH)
170 #define HALF_ENABLE_CPP11_CMATH 1
171 #endif
172 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_HASH)
173 #define HALF_ENABLE_CPP11_HASH 1
174 #endif
175 #if HALF_GCC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_CFENV)
176 #define HALF_ENABLE_CPP11_CFENV 1
177 #endif
178 #endif
179 #endif
180 #elif defined(_CPPLIB_VER) // Dinkumware/Visual C++
181 #if _CPPLIB_VER >= 520 && !defined(HALF_ENABLE_CPP11_TYPE_TRAITS)
182 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
183 #endif
184 #if _CPPLIB_VER >= 520 && !defined(HALF_ENABLE_CPP11_CSTDINT)
185 #define HALF_ENABLE_CPP11_CSTDINT 1
186 #endif
187 #if _CPPLIB_VER >= 520 && !defined(HALF_ENABLE_CPP11_HASH)
188 #define HALF_ENABLE_CPP11_HASH 1
189 #endif
190 #if _CPPLIB_VER >= 610 && !defined(HALF_ENABLE_CPP11_CMATH)
191 #define HALF_ENABLE_CPP11_CMATH 1
192 #endif
193 #if _CPPLIB_VER >= 610 && !defined(HALF_ENABLE_CPP11_CFENV)
194 #define HALF_ENABLE_CPP11_CFENV 1
195 #endif
196 #endif
197 #undef HALF_GCC_VERSION
198 #undef HALF_ICC_VERSION
199 
200 // any error throwing C++ exceptions?
201 #if defined(HALF_ERRHANDLING_THROW_INVALID) || defined(HALF_ERRHANDLING_THROW_DIVBYZERO) || \
202  defined(HALF_ERRHANDLING_THROW_OVERFLOW) || defined(HALF_ERRHANDLING_THROW_UNDERFLOW) || \
203  defined(HALF_ERRHANDLING_THROW_INEXACT)
204 #define HALF_ERRHANDLING_THROWS 1
205 #endif
206 
207 // any error handling enabled?
208 #define HALF_ERRHANDLING \
209  (HALF_ERRHANDLING_FLAGS || HALF_ERRHANDLING_ERRNO || HALF_ERRHANDLING_FENV || HALF_ERRHANDLING_THROWS)
210 
211 #if HALF_ERRHANDLING
212 #define HALF_UNUSED_NOERR(name) name
213 #else
214 #define HALF_UNUSED_NOERR(name)
215 #endif
216 
217 // support constexpr
218 #if HALF_ENABLE_CPP11_CONSTEXPR
219 #define HALF_CONSTEXPR constexpr
220 #define HALF_CONSTEXPR_CONST constexpr
221 #if HALF_ERRHANDLING
222 #define HALF_CONSTEXPR_NOERR
223 #else
224 #define HALF_CONSTEXPR_NOERR constexpr
225 #endif
226 #else
227 #define HALF_CONSTEXPR
228 #define HALF_CONSTEXPR_CONST const
229 #define HALF_CONSTEXPR_NOERR
230 #endif
231 
232 // support noexcept
233 #if HALF_ENABLE_CPP11_NOEXCEPT
234 #define HALF_NOEXCEPT noexcept
235 #define HALF_NOTHROW noexcept
236 #else
237 #define HALF_NOEXCEPT
238 #define HALF_NOTHROW throw()
239 #endif
240 
241 // support thread storage
242 #if HALF_ENABLE_CPP11_THREAD_LOCAL
243 #define HALF_THREAD_LOCAL thread_local
244 #else
245 #define HALF_THREAD_LOCAL static
246 #endif
247 
248 #include <algorithm>
249 #include <climits>
250 #include <cmath>
251 #include <cstdlib>
252 #include <cstring>
253 #include <istream>
254 #include <limits>
255 #include <ostream>
256 #include <stdexcept>
257 #include <utility>
258 #if HALF_ENABLE_CPP11_TYPE_TRAITS
259 #include <type_traits>
260 #endif
261 #if HALF_ENABLE_CPP11_CSTDINT
262 #include <cstdint>
263 #endif
264 #if HALF_ERRHANDLING_ERRNO
265 #include <cerrno>
266 #endif
267 #if HALF_ENABLE_CPP11_CFENV
268 #include <cfenv>
269 #endif
270 #if HALF_ENABLE_CPP11_HASH
271 #include <functional>
272 #endif
273 
274 #ifndef HALF_ENABLE_F16C_INTRINSICS
283 #define HALF_ENABLE_F16C_INTRINSICS __F16C__
284 #endif
285 #if HALF_ENABLE_F16C_INTRINSICS
286 #include <immintrin.h>
287 #endif
288 
289 #ifdef HALF_DOXYGEN_ONLY
296 #define HALF_ARITHMETIC_TYPE (undefined)
297 
301 #define HALF_ERRHANDLING_FLAGS 0
302 
308 #define HALF_ERRHANDLING_ERRNO 0
309 
316 #define HALF_ERRHANDLING_FENV 0
317 
322 #define HALF_ERRHANDLING_THROW_INVALID (undefined)
323 
327 #define HALF_ERRHANDLING_THROW_DIVBYZERO (undefined)
328 
333 #define HALF_ERRHANDLING_THROW_OVERFLOW (undefined)
334 
339 #define HALF_ERRHANDLING_THROW_UNDERFLOW (undefined)
340 
345 #define HALF_ERRHANDLING_THROW_INEXACT (undefined)
346 #endif
347 
348 #ifndef HALF_ERRHANDLING_OVERFLOW_TO_INEXACT
352 #define HALF_ERRHANDLING_OVERFLOW_TO_INEXACT 1
353 #endif
354 
355 #ifndef HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT
363 #define HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT 1
364 #endif
365 
386 #ifndef HALF_ROUND_STYLE
387 #define HALF_ROUND_STYLE 1 // = std::round_to_nearest
388 #endif
389 
395 #define HUGE_VALH std::numeric_limits<half_float::half>::infinity()
396 
402 #define FP_FAST_FMAH 1
403 
409 #define HLF_ROUNDS HALF_ROUND_STYLE
410 
411 #ifndef FP_ILOGB0
412 #define FP_ILOGB0 INT_MIN
413 #endif
414 #ifndef FP_ILOGBNAN
415 #define FP_ILOGBNAN INT_MAX
416 #endif
417 #ifndef FP_SUBNORMAL
418 #define FP_SUBNORMAL 0
419 #endif
420 #ifndef FP_ZERO
421 #define FP_ZERO 1
422 #endif
423 #ifndef FP_NAN
424 #define FP_NAN 2
425 #endif
426 #ifndef FP_INFINITE
427 #define FP_INFINITE 3
428 #endif
429 #ifndef FP_NORMAL
430 #define FP_NORMAL 4
431 #endif
432 
433 #if !HALF_ENABLE_CPP11_CFENV && !defined(FE_ALL_EXCEPT)
434 #define FE_INVALID 0x10
435 #define FE_DIVBYZERO 0x08
436 #define FE_OVERFLOW 0x04
437 #define FE_UNDERFLOW 0x02
438 #define FE_INEXACT 0x01
439 #define FE_ALL_EXCEPT (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
440 #endif
441 
444 namespace half_float {
445 class half;
446 
447 #if HALF_ENABLE_CPP11_USER_LITERALS
454 namespace literal {
455  half operator"" _h(long double);
456 }
457 #endif
458 
461 namespace detail {
462 #if HALF_ENABLE_CPP11_TYPE_TRAITS
464  template <bool B, typename T, typename F> struct conditional : std::conditional<B, T, F> {
465  };
466 
468  template <bool B> struct bool_type : std::integral_constant<bool, B> {
469  };
470  using std::false_type;
471  using std::true_type;
472 
474  template <typename T> struct is_float : std::is_floating_point<T> {
475  };
476 #else
478  template <bool, typename T, typename> struct conditional {
479  typedef T type;
480  };
481  template <typename T, typename F> struct conditional<false, T, F> {
482  typedef F type;
483  };
484 
486  template <bool> struct bool_type {
487  };
490 
492  template <typename> struct is_float : false_type {
493  };
494  template <typename T> struct is_float<const T> : is_float<T> {
495  };
496  template <typename T> struct is_float<volatile T> : is_float<T> {
497  };
498  template <typename T> struct is_float<const volatile T> : is_float<T> {
499  };
500  template <> struct is_float<float> : true_type {
501  };
502  template <> struct is_float<double> : true_type {
503  };
504  template <> struct is_float<long double> : true_type {
505  };
506 #endif
507 
509  template <typename T> struct bits {
510  typedef unsigned char type;
511  };
512  template <typename T> struct bits<const T> : bits<T> {
513  };
514  template <typename T> struct bits<volatile T> : bits<T> {
515  };
516  template <typename T> struct bits<const volatile T> : bits<T> {
517  };
518 
519 #if HALF_ENABLE_CPP11_CSTDINT
521  typedef std::uint_least16_t uint16;
522 
524  typedef std::uint_fast32_t uint32;
525 
527  typedef std::int_fast32_t int32;
528 
530  template <> struct bits<float> {
531  typedef std::uint_least32_t type;
532  };
533 
535  template <> struct bits<double> {
536  typedef std::uint_least64_t type;
537  };
538 #else
540  typedef unsigned short uint16;
541 
543  typedef unsigned long uint32;
544 
546  typedef long int32;
547 
549  template <>
550  struct bits<float> : conditional<std::numeric_limits<unsigned int>::digits >= 32, unsigned int, unsigned long> {
551  };
552 
553 #if HALF_ENABLE_CPP11_LONG_LONG
555  template <>
556  struct bits<double>
557  : conditional<std::numeric_limits<unsigned long>::digits >= 64, unsigned long, unsigned long long> {
558  };
559 #else
561  template <> struct bits<double> {
562  typedef unsigned long type;
563  };
564 #endif
565 #endif
566 
567 #ifdef HALF_ARITHMETIC_TYPE
569  typedef HALF_ARITHMETIC_TYPE internal_t;
570 #endif
571 
573  struct binary_t {};
574 
577 
580 
586  template <typename T> bool builtin_isinf(T arg)
587  {
588 #if HALF_ENABLE_CPP11_CMATH
589  return std::isinf(arg);
590 #elif defined(_MSC_VER)
591  return !::_finite(static_cast<double>(arg)) && !::_isnan(static_cast<double>(arg));
592 #else
593  return arg == std::numeric_limits<T>::infinity() || arg == -std::numeric_limits<T>::infinity();
594 #endif
595  }
596 
602  template <typename T> bool builtin_isnan(T arg)
603  {
604 #if HALF_ENABLE_CPP11_CMATH
605  return std::isnan(arg);
606 #elif defined(_MSC_VER)
607  return ::_isnan(static_cast<double>(arg)) != 0;
608 #else
609  return arg != arg;
610 #endif
611  }
612 
618  template <typename T> bool builtin_signbit(T arg)
619  {
620 #if HALF_ENABLE_CPP11_CMATH
621  return std::signbit(arg);
622 #else
623  return arg < T() || (arg == T() && T(1) / arg < T());
624 #endif
625  }
626 
631  inline uint32 sign_mask(uint32 arg)
632  {
633  static const int N = std::numeric_limits<uint32>::digits - 1;
634 #if HALF_TWOS_COMPLEMENT_INT
635  return static_cast<int32>(arg) >> N;
636 #else
637  return -((arg >> N) & 1);
638 #endif
639  }
640 
645  inline uint32 arithmetic_shift(uint32 arg, int i)
646  {
647 #if HALF_TWOS_COMPLEMENT_INT
648  return static_cast<int32>(arg) >> i;
649 #else
650  return static_cast<int32>(arg) / (static_cast<int32>(1) << i) -
651  ((arg >> (std::numeric_limits<uint32>::digits - 1)) & 1);
652 #endif
653  }
654 
658 
661  inline int& errflags()
662  {
663  HALF_THREAD_LOCAL int flags = 0;
664  return flags;
665  }
666 
670  inline void raise(int HALF_UNUSED_NOERR(flags), bool HALF_UNUSED_NOERR(cond) = true)
671  {
672 #if HALF_ERRHANDLING
673  if (!cond)
674  return;
675 #if HALF_ERRHANDLING_FLAGS
676  errflags() |= flags;
677 #endif
678 #if HALF_ERRHANDLING_ERRNO
679  if (flags & FE_INVALID)
680  errno = EDOM;
681  else if (flags & (FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))
682  errno = ERANGE;
683 #endif
684 #if HALF_ERRHANDLING_FENV && HALF_ENABLE_CPP11_CFENV
685  std::feraiseexcept(flags);
686 #endif
687 #ifdef HALF_ERRHANDLING_THROW_INVALID
688  if (flags & FE_INVALID)
689  throw std::domain_error(HALF_ERRHANDLING_THROW_INVALID);
690 #endif
691 #ifdef HALF_ERRHANDLING_THROW_DIVBYZERO
692  if (flags & FE_DIVBYZERO)
693  throw std::domain_error(HALF_ERRHANDLING_THROW_DIVBYZERO);
694 #endif
695 #ifdef HALF_ERRHANDLING_THROW_OVERFLOW
696  if (flags & FE_OVERFLOW)
697  throw std::overflow_error(HALF_ERRHANDLING_THROW_OVERFLOW);
698 #endif
699 #ifdef HALF_ERRHANDLING_THROW_UNDERFLOW
700  if (flags & FE_UNDERFLOW)
701  throw std::underflow_error(HALF_ERRHANDLING_THROW_UNDERFLOW);
702 #endif
703 #ifdef HALF_ERRHANDLING_THROW_INEXACT
704  if (flags & FE_INEXACT)
705  throw std::range_error(HALF_ERRHANDLING_THROW_INEXACT);
706 #endif
707 #if HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT
708  if ((flags & FE_UNDERFLOW) && !(flags & FE_INEXACT))
709  raise(FE_INEXACT);
710 #endif
711 #if HALF_ERRHANDLING_OVERFLOW_TO_INEXACT
712  if ((flags & FE_OVERFLOW) && !(flags & FE_INEXACT))
713  raise(FE_INEXACT);
714 #endif
715 #endif
716  }
717 
724  inline HALF_CONSTEXPR_NOERR bool compsignal(unsigned int x, unsigned int y)
725  {
726 #if HALF_ERRHANDLING
727  raise(FE_INVALID, (x & 0x7FFF) > 0x7C00 || (y & 0x7FFF) > 0x7C00);
728 #endif
729  return (x & 0x7FFF) > 0x7C00 || (y & 0x7FFF) > 0x7C00;
730  }
731 
736  inline HALF_CONSTEXPR_NOERR unsigned int signal(unsigned int nan)
737  {
738 #if HALF_ERRHANDLING
739  raise(FE_INVALID, !(nan & 0x200));
740 #endif
741  return nan | 0x200;
742  }
743 
749  inline HALF_CONSTEXPR_NOERR unsigned int signal(unsigned int x, unsigned int y)
750  {
751 #if HALF_ERRHANDLING
752  raise(FE_INVALID, ((x & 0x7FFF) > 0x7C00 && !(x & 0x200)) || ((y & 0x7FFF) > 0x7C00 && !(y & 0x200)));
753 #endif
754  return ((x & 0x7FFF) > 0x7C00) ? (x | 0x200) : (y | 0x200);
755  }
756 
763  inline HALF_CONSTEXPR_NOERR unsigned int signal(unsigned int x, unsigned int y, unsigned int z)
764  {
765 #if HALF_ERRHANDLING
766  raise(FE_INVALID,
767  ((x & 0x7FFF) > 0x7C00 && !(x & 0x200)) || ((y & 0x7FFF) > 0x7C00 && !(y & 0x200)) ||
768  ((z & 0x7FFF) > 0x7C00 && !(z & 0x200)));
769 #endif
770  return ((x & 0x7FFF) > 0x7C00) ? (x | 0x200) : ((y & 0x7FFF) > 0x7C00) ? (y | 0x200) : (z | 0x200);
771  }
772 
778  inline HALF_CONSTEXPR_NOERR unsigned int select(unsigned int x, unsigned int HALF_UNUSED_NOERR(y))
779  {
780 #if HALF_ERRHANDLING
781  return (((y & 0x7FFF) > 0x7C00) && !(y & 0x200)) ? signal(y) : x;
782 #else
783  return x;
784 #endif
785  }
786 
790  inline HALF_CONSTEXPR_NOERR unsigned int invalid()
791  {
792 #if HALF_ERRHANDLING
793  raise(FE_INVALID);
794 #endif
795  return 0x7FFF;
796  }
797 
802  inline HALF_CONSTEXPR_NOERR unsigned int pole(unsigned int sign = 0)
803  {
804 #if HALF_ERRHANDLING
805  raise(FE_DIVBYZERO);
806 #endif
807  return sign | 0x7C00;
808  }
809 
814  inline HALF_CONSTEXPR_NOERR unsigned int check_underflow(unsigned int arg)
815  {
816 #if HALF_ERRHANDLING && !HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT
817  raise(FE_UNDERFLOW, !(arg & 0x7C00));
818 #endif
819  return arg;
820  }
821 
825 
831  template <std::float_round_style R> HALF_CONSTEXPR_NOERR unsigned int overflow(unsigned int sign = 0)
832  {
833 #if HALF_ERRHANDLING
834  raise(FE_OVERFLOW);
835 #endif
836  return (R == std::round_toward_infinity) ? (sign + 0x7C00 - (sign >> 15))
837  : (R == std::round_toward_neg_infinity) ? (sign + 0x7BFF + (sign >> 15))
838  : (R == std::round_toward_zero) ? (sign | 0x7BFF)
839  : (sign | 0x7C00);
840  }
841 
847  template <std::float_round_style R> HALF_CONSTEXPR_NOERR unsigned int underflow(unsigned int sign = 0)
848  {
849 #if HALF_ERRHANDLING
850  raise(FE_UNDERFLOW);
851 #endif
852  return (R == std::round_toward_infinity) ? (sign + 1 - (sign >> 15))
853  : (R == std::round_toward_neg_infinity) ? (sign + (sign >> 15))
854  : sign;
855  }
856 
867  template <std::float_round_style R, bool I>
868  HALF_CONSTEXPR_NOERR unsigned int rounded(unsigned int value, int g, int s)
869  {
870 #if HALF_ERRHANDLING
871  value += (R == std::round_to_nearest) ? (g & (s | value))
872  : (R == std::round_toward_infinity) ? (~(value >> 15) & (g | s))
873  : (R == std::round_toward_neg_infinity) ? ((value >> 15) & (g | s))
874  : 0;
875  if ((value & 0x7C00) == 0x7C00)
876  raise(FE_OVERFLOW);
877  else if (value & 0x7C00)
878  raise(FE_INEXACT, I || (g | s) != 0);
879  else
880  raise(FE_UNDERFLOW, !(HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT) || I || (g | s) != 0);
881  return value;
882 #else
883  return (R == std::round_to_nearest) ? (value + (g & (s | value)))
884  : (R == std::round_toward_infinity) ? (value + (~(value >> 15) & (g | s)))
885  : (R == std::round_toward_neg_infinity) ? (value + ((value >> 15) & (g | s)))
886  : value;
887 #endif
888  }
889 
898  template <std::float_round_style R, bool E, bool I> unsigned int integral(unsigned int value)
899  {
900  unsigned int abs = value & 0x7FFF;
901  if (abs < 0x3C00) {
902  raise(FE_INEXACT, I);
903  return ((R == std::round_to_nearest) ? (0x3C00 & -static_cast<unsigned>(abs >= (0x3800 + E)))
904  : (R == std::round_toward_infinity) ? (0x3C00 & -(~(value >> 15) & (abs != 0)))
905  : (R == std::round_toward_neg_infinity) ? (0x3C00 & -static_cast<unsigned>(value > 0x8000))
906  : 0) |
907  (value & 0x8000);
908  }
909  if (abs >= 0x6400)
910  return (abs > 0x7C00) ? signal(value) : value;
911  unsigned int exp = 25 - (abs >> 10), mask = (1 << exp) - 1;
912  raise(FE_INEXACT, I && (value & mask));
913  return (((R == std::round_to_nearest) ? ((1 << (exp - 1)) - (~(value >> exp) & E))
914  : (R == std::round_toward_infinity) ? (mask & ((value >> 15) - 1))
915  : (R == std::round_toward_neg_infinity) ? (mask & -(value >> 15))
916  : 0) +
917  value) &
918  ~mask;
919  }
920 
935  template <std::float_round_style R, unsigned int F, bool S, bool N, bool I>
936  unsigned int fixed2half(uint32 m, int exp = 14, unsigned int sign = 0, int s = 0)
937  {
938  if (S) {
939  uint32 msign = sign_mask(m);
940  m = (m ^ msign) - msign;
941  sign = msign & 0x8000;
942  }
943  if (N)
944  for (; m < (static_cast<uint32>(1) << F) && exp; m <<= 1, --exp)
945  ;
946  else if (exp < 0)
947  return rounded<R, I>(sign + (m >> (F - 10 - exp)), (m >> (F - 11 - exp)) & 1,
948  s | ((m & ((static_cast<uint32>(1) << (F - 11 - exp)) - 1)) != 0));
949  return rounded<R, I>(sign + (exp << 10) + (m >> (F - 10)), (m >> (F - 11)) & 1,
950  s | ((m & ((static_cast<uint32>(1) << (F - 11)) - 1)) != 0));
951  }
952 
961  template <std::float_round_style R> unsigned int float2half_impl(float value, true_type)
962  {
963 #if HALF_ENABLE_F16C_INTRINSICS
964  return _mm_cvtsi128_si32(_mm_cvtps_ph(_mm_set_ss(value),
965  (R == std::round_to_nearest) ? _MM_FROUND_TO_NEAREST_INT
966  : (R == std::round_toward_zero) ? _MM_FROUND_TO_ZERO
967  : (R == std::round_toward_infinity) ? _MM_FROUND_TO_POS_INF
968  : (R == std::round_toward_neg_infinity) ? _MM_FROUND_TO_NEG_INF
969  : _MM_FROUND_CUR_DIRECTION));
970 #else
971  bits<float>::type fbits;
972  std::memcpy(&fbits, &value, sizeof(float));
973 #if 1
974  unsigned int sign = (fbits >> 16) & 0x8000;
975  fbits &= 0x7FFFFFFF;
976  if (fbits >= 0x7F800000)
977  return sign | 0x7C00 | ((fbits > 0x7F800000) ? (0x200 | ((fbits >> 13) & 0x3FF)) : 0);
978  if (fbits >= 0x47800000)
979  return overflow<R>(sign);
980  if (fbits >= 0x38800000)
981  return rounded<R, false>(sign | (((fbits >> 23) - 112) << 10) | ((fbits >> 13) & 0x3FF), (fbits >> 12) & 1,
982  (fbits & 0xFFF) != 0);
983  if (fbits >= 0x33000000) {
984  int i = 125 - (fbits >> 23);
985  fbits = (fbits & 0x7FFFFF) | 0x800000;
986  return rounded<R, false>(
987  sign | (fbits >> (i + 1)), (fbits >> i) & 1, (fbits & ((static_cast<uint32>(1) << i) - 1)) != 0);
988  }
989  if (fbits != 0)
990  return underflow<R>(sign);
991  return sign;
992 #else
993  static const uint16 base_table[512] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
994  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
995  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
996  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
997  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
998  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
999  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1000  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1001  0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,
1002  0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, 0x2C00, 0x3000, 0x3400,
1003  0x3800, 0x3C00, 0x4000, 0x4400, 0x4800, 0x4C00, 0x5000, 0x5400, 0x5800, 0x5C00, 0x6000, 0x6400, 0x6800,
1004  0x6C00, 0x7000, 0x7400, 0x7800, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1005  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1006  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1007  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1008  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1009  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1010  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1011  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF,
1012  0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7BFF, 0x7C00,
1013  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1014  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1015  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1016  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1017  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1018  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1019  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
1020  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001,
1021  0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400, 0x8800, 0x8C00, 0x9000,
1022  0x9400, 0x9800, 0x9C00, 0xA000, 0xA400, 0xA800, 0xAC00, 0xB000, 0xB400, 0xB800, 0xBC00, 0xC000, 0xC400,
1023  0xC800, 0xCC00, 0xD000, 0xD400, 0xD800, 0xDC00, 0xE000, 0xE400, 0xE800, 0xEC00, 0xF000, 0xF400, 0xF800,
1024  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1025  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1026  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1027  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1028  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1029  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1030  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1031  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF,
1032  0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFBFF, 0xFC00 };
1033  static const unsigned char shift_table[256] = { 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
1034  25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
1035  25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
1036  25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
1037  25, 25, 25, 25, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
1038  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24,
1039  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
1040  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
1041  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
1042  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 };
1043  int sexp = fbits >> 23, exp = sexp & 0xFF, i = shift_table[exp];
1044  fbits &= 0x7FFFFF;
1045  uint32 m = (fbits | ((exp != 0) << 23)) & -static_cast<uint32>(exp != 0xFF);
1046  return rounded<R, false>(
1047  base_table[sexp] + (fbits >> i), (m >> (i - 1)) & 1, (((static_cast<uint32>(1) << (i - 1)) - 1) & m) != 0);
1048 #endif
1049 #endif
1050  }
1051 
1059  template <std::float_round_style R> unsigned int float2half_impl(double value, true_type)
1060  {
1061 #if HALF_ENABLE_F16C_INTRINSICS
1062  if (R == std::round_indeterminate)
1063  return _mm_cvtsi128_si32(_mm_cvtps_ph(_mm_cvtpd_ps(_mm_set_sd(value)), _MM_FROUND_CUR_DIRECTION));
1064 #endif
1065  bits<double>::type dbits;
1066  std::memcpy(&dbits, &value, sizeof(double));
1067  uint32 hi = dbits >> 32, lo = dbits & 0xFFFFFFFF;
1068  unsigned int sign = (hi >> 16) & 0x8000;
1069  hi &= 0x7FFFFFFF;
1070  if (hi >= 0x7FF00000)
1071  return sign | 0x7C00 | ((dbits & 0xFFFFFFFFFFFFF) ? (0x200 | ((hi >> 10) & 0x3FF)) : 0);
1072  if (hi >= 0x40F00000)
1073  return overflow<R>(sign);
1074  if (hi >= 0x3F100000)
1075  return rounded<R, false>(
1076  sign | (((hi >> 20) - 1008) << 10) | ((hi >> 10) & 0x3FF), (hi >> 9) & 1, ((hi & 0x1FF) | lo) != 0);
1077  if (hi >= 0x3E600000) {
1078  int i = 1018 - (hi >> 20);
1079  hi = (hi & 0xFFFFF) | 0x100000;
1080  return rounded<R, false>(
1081  sign | (hi >> (i + 1)), (hi >> i) & 1, ((hi & ((static_cast<uint32>(1) << i) - 1)) | lo) != 0);
1082  }
1083  if ((hi | lo) != 0)
1084  return underflow<R>(sign);
1085  return sign;
1086  }
1087 
1096  template <std::float_round_style R, typename T> unsigned int float2half_impl(T value, ...)
1097  {
1098  unsigned int hbits = static_cast<unsigned>(builtin_signbit(value)) << 15;
1099  if (value == T())
1100  return hbits;
1101  if (builtin_isnan(value))
1102  return hbits | 0x7FFF;
1103  if (builtin_isinf(value))
1104  return hbits | 0x7C00;
1105  int exp;
1106  std::frexp(value, &exp);
1107  if (exp > 16)
1108  return overflow<R>(hbits);
1109  if (exp < -13)
1110  value = std::ldexp(value, 25);
1111  else {
1112  value = std::ldexp(value, 12 - exp);
1113  hbits |= ((exp + 13) << 10);
1114  }
1115  T ival, frac = std::modf(value, &ival);
1116  int m = std::abs(static_cast<int>(ival));
1117  return rounded<R, false>(hbits + (m >> 1), m & 1, frac != T());
1118  }
1119 
1128  template <std::float_round_style R, typename T> unsigned int float2half(T value)
1129  {
1130  return float2half_impl<R>(
1131  value, bool_type < std::numeric_limits<T>::is_iec559 && sizeof(typename bits<T>::type) == sizeof(T) > ());
1132  }
1133 
1141  template <std::float_round_style R, typename T> unsigned int int2half(T value)
1142  {
1143  unsigned int bits = static_cast<unsigned>(value < 0) << 15;
1144  if (!value)
1145  return bits;
1146  if (bits)
1147  value = -value;
1148  if (value > 0xFFFF)
1149  return overflow<R>(bits);
1150  unsigned int m = static_cast<unsigned int>(value), exp = 24;
1151  for (; m < 0x400; m <<= 1, --exp)
1152  ;
1153  for (; m > 0x7FF; m >>= 1, ++exp)
1154  ;
1155  bits |= (exp << 10) + m;
1156  return (exp > 24) ? rounded<R, false>(bits, (value >> (exp - 25)) & 1, (((1 << (exp - 25)) - 1) & value) != 0)
1157  : bits;
1158  }
1159 
1164  inline float half2float_impl(unsigned int value, float, true_type)
1165  {
1166 #if HALF_ENABLE_F16C_INTRINSICS
1167  return _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(value)));
1168 #else
1169 #if 0
1170  bits<float>::type fbits = static_cast<bits<float>::type>(value&0x8000) << 16;
1171  int abs = value & 0x7FFF;
1172  if(abs)
1173  {
1174  fbits |= 0x38000000 << static_cast<unsigned>(abs>=0x7C00);
1175  for(; abs<0x400; abs<<=1,fbits-=0x800000) ;
1176  fbits += static_cast<bits<float>::type>(abs) << 13;
1177  }
1178 #else
1179  static const bits<float>::type mantissa_table[2048] = { 0x00000000, 0x33800000, 0x34000000, 0x34400000,
1180  0x34800000, 0x34A00000, 0x34C00000, 0x34E00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000, 0x35400000,
1181  0x35500000, 0x35600000, 0x35700000, 0x35800000, 0x35880000, 0x35900000, 0x35980000, 0x35A00000, 0x35A80000,
1182  0x35B00000, 0x35B80000, 0x35C00000, 0x35C80000, 0x35D00000, 0x35D80000, 0x35E00000, 0x35E80000, 0x35F00000,
1183  0x35F80000, 0x36000000, 0x36040000, 0x36080000, 0x360C0000, 0x36100000, 0x36140000, 0x36180000, 0x361C0000,
1184  0x36200000, 0x36240000, 0x36280000, 0x362C0000, 0x36300000, 0x36340000, 0x36380000, 0x363C0000, 0x36400000,
1185  0x36440000, 0x36480000, 0x364C0000, 0x36500000, 0x36540000, 0x36580000, 0x365C0000, 0x36600000, 0x36640000,
1186  0x36680000, 0x366C0000, 0x36700000, 0x36740000, 0x36780000, 0x367C0000, 0x36800000, 0x36820000, 0x36840000,
1187  0x36860000, 0x36880000, 0x368A0000, 0x368C0000, 0x368E0000, 0x36900000, 0x36920000, 0x36940000, 0x36960000,
1188  0x36980000, 0x369A0000, 0x369C0000, 0x369E0000, 0x36A00000, 0x36A20000, 0x36A40000, 0x36A60000, 0x36A80000,
1189  0x36AA0000, 0x36AC0000, 0x36AE0000, 0x36B00000, 0x36B20000, 0x36B40000, 0x36B60000, 0x36B80000, 0x36BA0000,
1190  0x36BC0000, 0x36BE0000, 0x36C00000, 0x36C20000, 0x36C40000, 0x36C60000, 0x36C80000, 0x36CA0000, 0x36CC0000,
1191  0x36CE0000, 0x36D00000, 0x36D20000, 0x36D40000, 0x36D60000, 0x36D80000, 0x36DA0000, 0x36DC0000, 0x36DE0000,
1192  0x36E00000, 0x36E20000, 0x36E40000, 0x36E60000, 0x36E80000, 0x36EA0000, 0x36EC0000, 0x36EE0000, 0x36F00000,
1193  0x36F20000, 0x36F40000, 0x36F60000, 0x36F80000, 0x36FA0000, 0x36FC0000, 0x36FE0000, 0x37000000, 0x37010000,
1194  0x37020000, 0x37030000, 0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000, 0x370A0000,
1195  0x370B0000, 0x370C0000, 0x370D0000, 0x370E0000, 0x370F0000, 0x37100000, 0x37110000, 0x37120000, 0x37130000,
1196  0x37140000, 0x37150000, 0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371A0000, 0x371B0000, 0x371C0000,
1197  0x371D0000, 0x371E0000, 0x371F0000, 0x37200000, 0x37210000, 0x37220000, 0x37230000, 0x37240000, 0x37250000,
1198  0x37260000, 0x37270000, 0x37280000, 0x37290000, 0x372A0000, 0x372B0000, 0x372C0000, 0x372D0000, 0x372E0000,
1199  0x372F0000, 0x37300000, 0x37310000, 0x37320000, 0x37330000, 0x37340000, 0x37350000, 0x37360000, 0x37370000,
1200  0x37380000, 0x37390000, 0x373A0000, 0x373B0000, 0x373C0000, 0x373D0000, 0x373E0000, 0x373F0000, 0x37400000,
1201  0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, 0x37460000, 0x37470000, 0x37480000, 0x37490000,
1202  0x374A0000, 0x374B0000, 0x374C0000, 0x374D0000, 0x374E0000, 0x374F0000, 0x37500000, 0x37510000, 0x37520000,
1203  0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000, 0x37580000, 0x37590000, 0x375A0000, 0x375B0000,
1204  0x375C0000, 0x375D0000, 0x375E0000, 0x375F0000, 0x37600000, 0x37610000, 0x37620000, 0x37630000, 0x37640000,
1205  0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000, 0x376A0000, 0x376B0000, 0x376C0000, 0x376D0000,
1206  0x376E0000, 0x376F0000, 0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, 0x37760000,
1207  0x37770000, 0x37780000, 0x37790000, 0x377A0000, 0x377B0000, 0x377C0000, 0x377D0000, 0x377E0000, 0x377F0000,
1208  0x37800000, 0x37808000, 0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000, 0x37840000,
1209  0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, 0x37870000, 0x37878000, 0x37880000, 0x37888000,
1210  0x37890000, 0x37898000, 0x378A0000, 0x378A8000, 0x378B0000, 0x378B8000, 0x378C0000, 0x378C8000, 0x378D0000,
1211  0x378D8000, 0x378E0000, 0x378E8000, 0x378F0000, 0x378F8000, 0x37900000, 0x37908000, 0x37910000, 0x37918000,
1212  0x37920000, 0x37928000, 0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000, 0x37960000,
1213  0x37968000, 0x37970000, 0x37978000, 0x37980000, 0x37988000, 0x37990000, 0x37998000, 0x379A0000, 0x379A8000,
1214  0x379B0000, 0x379B8000, 0x379C0000, 0x379C8000, 0x379D0000, 0x379D8000, 0x379E0000, 0x379E8000, 0x379F0000,
1215  0x379F8000, 0x37A00000, 0x37A08000, 0x37A10000, 0x37A18000, 0x37A20000, 0x37A28000, 0x37A30000, 0x37A38000,
1216  0x37A40000, 0x37A48000, 0x37A50000, 0x37A58000, 0x37A60000, 0x37A68000, 0x37A70000, 0x37A78000, 0x37A80000,
1217  0x37A88000, 0x37A90000, 0x37A98000, 0x37AA0000, 0x37AA8000, 0x37AB0000, 0x37AB8000, 0x37AC0000, 0x37AC8000,
1218  0x37AD0000, 0x37AD8000, 0x37AE0000, 0x37AE8000, 0x37AF0000, 0x37AF8000, 0x37B00000, 0x37B08000, 0x37B10000,
1219  0x37B18000, 0x37B20000, 0x37B28000, 0x37B30000, 0x37B38000, 0x37B40000, 0x37B48000, 0x37B50000, 0x37B58000,
1220  0x37B60000, 0x37B68000, 0x37B70000, 0x37B78000, 0x37B80000, 0x37B88000, 0x37B90000, 0x37B98000, 0x37BA0000,
1221  0x37BA8000, 0x37BB0000, 0x37BB8000, 0x37BC0000, 0x37BC8000, 0x37BD0000, 0x37BD8000, 0x37BE0000, 0x37BE8000,
1222  0x37BF0000, 0x37BF8000, 0x37C00000, 0x37C08000, 0x37C10000, 0x37C18000, 0x37C20000, 0x37C28000, 0x37C30000,
1223  0x37C38000, 0x37C40000, 0x37C48000, 0x37C50000, 0x37C58000, 0x37C60000, 0x37C68000, 0x37C70000, 0x37C78000,
1224  0x37C80000, 0x37C88000, 0x37C90000, 0x37C98000, 0x37CA0000, 0x37CA8000, 0x37CB0000, 0x37CB8000, 0x37CC0000,
1225  0x37CC8000, 0x37CD0000, 0x37CD8000, 0x37CE0000, 0x37CE8000, 0x37CF0000, 0x37CF8000, 0x37D00000, 0x37D08000,
1226  0x37D10000, 0x37D18000, 0x37D20000, 0x37D28000, 0x37D30000, 0x37D38000, 0x37D40000, 0x37D48000, 0x37D50000,
1227  0x37D58000, 0x37D60000, 0x37D68000, 0x37D70000, 0x37D78000, 0x37D80000, 0x37D88000, 0x37D90000, 0x37D98000,
1228  0x37DA0000, 0x37DA8000, 0x37DB0000, 0x37DB8000, 0x37DC0000, 0x37DC8000, 0x37DD0000, 0x37DD8000, 0x37DE0000,
1229  0x37DE8000, 0x37DF0000, 0x37DF8000, 0x37E00000, 0x37E08000, 0x37E10000, 0x37E18000, 0x37E20000, 0x37E28000,
1230  0x37E30000, 0x37E38000, 0x37E40000, 0x37E48000, 0x37E50000, 0x37E58000, 0x37E60000, 0x37E68000, 0x37E70000,
1231  0x37E78000, 0x37E80000, 0x37E88000, 0x37E90000, 0x37E98000, 0x37EA0000, 0x37EA8000, 0x37EB0000, 0x37EB8000,
1232  0x37EC0000, 0x37EC8000, 0x37ED0000, 0x37ED8000, 0x37EE0000, 0x37EE8000, 0x37EF0000, 0x37EF8000, 0x37F00000,
1233  0x37F08000, 0x37F10000, 0x37F18000, 0x37F20000, 0x37F28000, 0x37F30000, 0x37F38000, 0x37F40000, 0x37F48000,
1234  0x37F50000, 0x37F58000, 0x37F60000, 0x37F68000, 0x37F70000, 0x37F78000, 0x37F80000, 0x37F88000, 0x37F90000,
1235  0x37F98000, 0x37FA0000, 0x37FA8000, 0x37FB0000, 0x37FB8000, 0x37FC0000, 0x37FC8000, 0x37FD0000, 0x37FD8000,
1236  0x37FE0000, 0x37FE8000, 0x37FF0000, 0x37FF8000, 0x38000000, 0x38004000, 0x38008000, 0x3800C000, 0x38010000,
1237  0x38014000, 0x38018000, 0x3801C000, 0x38020000, 0x38024000, 0x38028000, 0x3802C000, 0x38030000, 0x38034000,
1238  0x38038000, 0x3803C000, 0x38040000, 0x38044000, 0x38048000, 0x3804C000, 0x38050000, 0x38054000, 0x38058000,
1239  0x3805C000, 0x38060000, 0x38064000, 0x38068000, 0x3806C000, 0x38070000, 0x38074000, 0x38078000, 0x3807C000,
1240  0x38080000, 0x38084000, 0x38088000, 0x3808C000, 0x38090000, 0x38094000, 0x38098000, 0x3809C000, 0x380A0000,
1241  0x380A4000, 0x380A8000, 0x380AC000, 0x380B0000, 0x380B4000, 0x380B8000, 0x380BC000, 0x380C0000, 0x380C4000,
1242  0x380C8000, 0x380CC000, 0x380D0000, 0x380D4000, 0x380D8000, 0x380DC000, 0x380E0000, 0x380E4000, 0x380E8000,
1243  0x380EC000, 0x380F0000, 0x380F4000, 0x380F8000, 0x380FC000, 0x38100000, 0x38104000, 0x38108000, 0x3810C000,
1244  0x38110000, 0x38114000, 0x38118000, 0x3811C000, 0x38120000, 0x38124000, 0x38128000, 0x3812C000, 0x38130000,
1245  0x38134000, 0x38138000, 0x3813C000, 0x38140000, 0x38144000, 0x38148000, 0x3814C000, 0x38150000, 0x38154000,
1246  0x38158000, 0x3815C000, 0x38160000, 0x38164000, 0x38168000, 0x3816C000, 0x38170000, 0x38174000, 0x38178000,
1247  0x3817C000, 0x38180000, 0x38184000, 0x38188000, 0x3818C000, 0x38190000, 0x38194000, 0x38198000, 0x3819C000,
1248  0x381A0000, 0x381A4000, 0x381A8000, 0x381AC000, 0x381B0000, 0x381B4000, 0x381B8000, 0x381BC000, 0x381C0000,
1249  0x381C4000, 0x381C8000, 0x381CC000, 0x381D0000, 0x381D4000, 0x381D8000, 0x381DC000, 0x381E0000, 0x381E4000,
1250  0x381E8000, 0x381EC000, 0x381F0000, 0x381F4000, 0x381F8000, 0x381FC000, 0x38200000, 0x38204000, 0x38208000,
1251  0x3820C000, 0x38210000, 0x38214000, 0x38218000, 0x3821C000, 0x38220000, 0x38224000, 0x38228000, 0x3822C000,
1252  0x38230000, 0x38234000, 0x38238000, 0x3823C000, 0x38240000, 0x38244000, 0x38248000, 0x3824C000, 0x38250000,
1253  0x38254000, 0x38258000, 0x3825C000, 0x38260000, 0x38264000, 0x38268000, 0x3826C000, 0x38270000, 0x38274000,
1254  0x38278000, 0x3827C000, 0x38280000, 0x38284000, 0x38288000, 0x3828C000, 0x38290000, 0x38294000, 0x38298000,
1255  0x3829C000, 0x382A0000, 0x382A4000, 0x382A8000, 0x382AC000, 0x382B0000, 0x382B4000, 0x382B8000, 0x382BC000,
1256  0x382C0000, 0x382C4000, 0x382C8000, 0x382CC000, 0x382D0000, 0x382D4000, 0x382D8000, 0x382DC000, 0x382E0000,
1257  0x382E4000, 0x382E8000, 0x382EC000, 0x382F0000, 0x382F4000, 0x382F8000, 0x382FC000, 0x38300000, 0x38304000,
1258  0x38308000, 0x3830C000, 0x38310000, 0x38314000, 0x38318000, 0x3831C000, 0x38320000, 0x38324000, 0x38328000,
1259  0x3832C000, 0x38330000, 0x38334000, 0x38338000, 0x3833C000, 0x38340000, 0x38344000, 0x38348000, 0x3834C000,
1260  0x38350000, 0x38354000, 0x38358000, 0x3835C000, 0x38360000, 0x38364000, 0x38368000, 0x3836C000, 0x38370000,
1261  0x38374000, 0x38378000, 0x3837C000, 0x38380000, 0x38384000, 0x38388000, 0x3838C000, 0x38390000, 0x38394000,
1262  0x38398000, 0x3839C000, 0x383A0000, 0x383A4000, 0x383A8000, 0x383AC000, 0x383B0000, 0x383B4000, 0x383B8000,
1263  0x383BC000, 0x383C0000, 0x383C4000, 0x383C8000, 0x383CC000, 0x383D0000, 0x383D4000, 0x383D8000, 0x383DC000,
1264  0x383E0000, 0x383E4000, 0x383E8000, 0x383EC000, 0x383F0000, 0x383F4000, 0x383F8000, 0x383FC000, 0x38400000,
1265  0x38404000, 0x38408000, 0x3840C000, 0x38410000, 0x38414000, 0x38418000, 0x3841C000, 0x38420000, 0x38424000,
1266  0x38428000, 0x3842C000, 0x38430000, 0x38434000, 0x38438000, 0x3843C000, 0x38440000, 0x38444000, 0x38448000,
1267  0x3844C000, 0x38450000, 0x38454000, 0x38458000, 0x3845C000, 0x38460000, 0x38464000, 0x38468000, 0x3846C000,
1268  0x38470000, 0x38474000, 0x38478000, 0x3847C000, 0x38480000, 0x38484000, 0x38488000, 0x3848C000, 0x38490000,
1269  0x38494000, 0x38498000, 0x3849C000, 0x384A0000, 0x384A4000, 0x384A8000, 0x384AC000, 0x384B0000, 0x384B4000,
1270  0x384B8000, 0x384BC000, 0x384C0000, 0x384C4000, 0x384C8000, 0x384CC000, 0x384D0000, 0x384D4000, 0x384D8000,
1271  0x384DC000, 0x384E0000, 0x384E4000, 0x384E8000, 0x384EC000, 0x384F0000, 0x384F4000, 0x384F8000, 0x384FC000,
1272  0x38500000, 0x38504000, 0x38508000, 0x3850C000, 0x38510000, 0x38514000, 0x38518000, 0x3851C000, 0x38520000,
1273  0x38524000, 0x38528000, 0x3852C000, 0x38530000, 0x38534000, 0x38538000, 0x3853C000, 0x38540000, 0x38544000,
1274  0x38548000, 0x3854C000, 0x38550000, 0x38554000, 0x38558000, 0x3855C000, 0x38560000, 0x38564000, 0x38568000,
1275  0x3856C000, 0x38570000, 0x38574000, 0x38578000, 0x3857C000, 0x38580000, 0x38584000, 0x38588000, 0x3858C000,
1276  0x38590000, 0x38594000, 0x38598000, 0x3859C000, 0x385A0000, 0x385A4000, 0x385A8000, 0x385AC000, 0x385B0000,
1277  0x385B4000, 0x385B8000, 0x385BC000, 0x385C0000, 0x385C4000, 0x385C8000, 0x385CC000, 0x385D0000, 0x385D4000,
1278  0x385D8000, 0x385DC000, 0x385E0000, 0x385E4000, 0x385E8000, 0x385EC000, 0x385F0000, 0x385F4000, 0x385F8000,
1279  0x385FC000, 0x38600000, 0x38604000, 0x38608000, 0x3860C000, 0x38610000, 0x38614000, 0x38618000, 0x3861C000,
1280  0x38620000, 0x38624000, 0x38628000, 0x3862C000, 0x38630000, 0x38634000, 0x38638000, 0x3863C000, 0x38640000,
1281  0x38644000, 0x38648000, 0x3864C000, 0x38650000, 0x38654000, 0x38658000, 0x3865C000, 0x38660000, 0x38664000,
1282  0x38668000, 0x3866C000, 0x38670000, 0x38674000, 0x38678000, 0x3867C000, 0x38680000, 0x38684000, 0x38688000,
1283  0x3868C000, 0x38690000, 0x38694000, 0x38698000, 0x3869C000, 0x386A0000, 0x386A4000, 0x386A8000, 0x386AC000,
1284  0x386B0000, 0x386B4000, 0x386B8000, 0x386BC000, 0x386C0000, 0x386C4000, 0x386C8000, 0x386CC000, 0x386D0000,
1285  0x386D4000, 0x386D8000, 0x386DC000, 0x386E0000, 0x386E4000, 0x386E8000, 0x386EC000, 0x386F0000, 0x386F4000,
1286  0x386F8000, 0x386FC000, 0x38700000, 0x38704000, 0x38708000, 0x3870C000, 0x38710000, 0x38714000, 0x38718000,
1287  0x3871C000, 0x38720000, 0x38724000, 0x38728000, 0x3872C000, 0x38730000, 0x38734000, 0x38738000, 0x3873C000,
1288  0x38740000, 0x38744000, 0x38748000, 0x3874C000, 0x38750000, 0x38754000, 0x38758000, 0x3875C000, 0x38760000,
1289  0x38764000, 0x38768000, 0x3876C000, 0x38770000, 0x38774000, 0x38778000, 0x3877C000, 0x38780000, 0x38784000,
1290  0x38788000, 0x3878C000, 0x38790000, 0x38794000, 0x38798000, 0x3879C000, 0x387A0000, 0x387A4000, 0x387A8000,
1291  0x387AC000, 0x387B0000, 0x387B4000, 0x387B8000, 0x387BC000, 0x387C0000, 0x387C4000, 0x387C8000, 0x387CC000,
1292  0x387D0000, 0x387D4000, 0x387D8000, 0x387DC000, 0x387E0000, 0x387E4000, 0x387E8000, 0x387EC000, 0x387F0000,
1293  0x387F4000, 0x387F8000, 0x387FC000, 0x38000000, 0x38002000, 0x38004000, 0x38006000, 0x38008000, 0x3800A000,
1294  0x3800C000, 0x3800E000, 0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801A000, 0x3801C000,
1295  0x3801E000, 0x38020000, 0x38022000, 0x38024000, 0x38026000, 0x38028000, 0x3802A000, 0x3802C000, 0x3802E000,
1296  0x38030000, 0x38032000, 0x38034000, 0x38036000, 0x38038000, 0x3803A000, 0x3803C000, 0x3803E000, 0x38040000,
1297  0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804A000, 0x3804C000, 0x3804E000, 0x38050000, 0x38052000,
1298  0x38054000, 0x38056000, 0x38058000, 0x3805A000, 0x3805C000, 0x3805E000, 0x38060000, 0x38062000, 0x38064000,
1299  0x38066000, 0x38068000, 0x3806A000, 0x3806C000, 0x3806E000, 0x38070000, 0x38072000, 0x38074000, 0x38076000,
1300  0x38078000, 0x3807A000, 0x3807C000, 0x3807E000, 0x38080000, 0x38082000, 0x38084000, 0x38086000, 0x38088000,
1301  0x3808A000, 0x3808C000, 0x3808E000, 0x38090000, 0x38092000, 0x38094000, 0x38096000, 0x38098000, 0x3809A000,
1302  0x3809C000, 0x3809E000, 0x380A0000, 0x380A2000, 0x380A4000, 0x380A6000, 0x380A8000, 0x380AA000, 0x380AC000,
1303  0x380AE000, 0x380B0000, 0x380B2000, 0x380B4000, 0x380B6000, 0x380B8000, 0x380BA000, 0x380BC000, 0x380BE000,
1304  0x380C0000, 0x380C2000, 0x380C4000, 0x380C6000, 0x380C8000, 0x380CA000, 0x380CC000, 0x380CE000, 0x380D0000,
1305  0x380D2000, 0x380D4000, 0x380D6000, 0x380D8000, 0x380DA000, 0x380DC000, 0x380DE000, 0x380E0000, 0x380E2000,
1306  0x380E4000, 0x380E6000, 0x380E8000, 0x380EA000, 0x380EC000, 0x380EE000, 0x380F0000, 0x380F2000, 0x380F4000,
1307  0x380F6000, 0x380F8000, 0x380FA000, 0x380FC000, 0x380FE000, 0x38100000, 0x38102000, 0x38104000, 0x38106000,
1308  0x38108000, 0x3810A000, 0x3810C000, 0x3810E000, 0x38110000, 0x38112000, 0x38114000, 0x38116000, 0x38118000,
1309  0x3811A000, 0x3811C000, 0x3811E000, 0x38120000, 0x38122000, 0x38124000, 0x38126000, 0x38128000, 0x3812A000,
1310  0x3812C000, 0x3812E000, 0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813A000, 0x3813C000,
1311  0x3813E000, 0x38140000, 0x38142000, 0x38144000, 0x38146000, 0x38148000, 0x3814A000, 0x3814C000, 0x3814E000,
1312  0x38150000, 0x38152000, 0x38154000, 0x38156000, 0x38158000, 0x3815A000, 0x3815C000, 0x3815E000, 0x38160000,
1313  0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816A000, 0x3816C000, 0x3816E000, 0x38170000, 0x38172000,
1314  0x38174000, 0x38176000, 0x38178000, 0x3817A000, 0x3817C000, 0x3817E000, 0x38180000, 0x38182000, 0x38184000,
1315  0x38186000, 0x38188000, 0x3818A000, 0x3818C000, 0x3818E000, 0x38190000, 0x38192000, 0x38194000, 0x38196000,
1316  0x38198000, 0x3819A000, 0x3819C000, 0x3819E000, 0x381A0000, 0x381A2000, 0x381A4000, 0x381A6000, 0x381A8000,
1317  0x381AA000, 0x381AC000, 0x381AE000, 0x381B0000, 0x381B2000, 0x381B4000, 0x381B6000, 0x381B8000, 0x381BA000,
1318  0x381BC000, 0x381BE000, 0x381C0000, 0x381C2000, 0x381C4000, 0x381C6000, 0x381C8000, 0x381CA000, 0x381CC000,
1319  0x381CE000, 0x381D0000, 0x381D2000, 0x381D4000, 0x381D6000, 0x381D8000, 0x381DA000, 0x381DC000, 0x381DE000,
1320  0x381E0000, 0x381E2000, 0x381E4000, 0x381E6000, 0x381E8000, 0x381EA000, 0x381EC000, 0x381EE000, 0x381F0000,
1321  0x381F2000, 0x381F4000, 0x381F6000, 0x381F8000, 0x381FA000, 0x381FC000, 0x381FE000, 0x38200000, 0x38202000,
1322  0x38204000, 0x38206000, 0x38208000, 0x3820A000, 0x3820C000, 0x3820E000, 0x38210000, 0x38212000, 0x38214000,
1323  0x38216000, 0x38218000, 0x3821A000, 0x3821C000, 0x3821E000, 0x38220000, 0x38222000, 0x38224000, 0x38226000,
1324  0x38228000, 0x3822A000, 0x3822C000, 0x3822E000, 0x38230000, 0x38232000, 0x38234000, 0x38236000, 0x38238000,
1325  0x3823A000, 0x3823C000, 0x3823E000, 0x38240000, 0x38242000, 0x38244000, 0x38246000, 0x38248000, 0x3824A000,
1326  0x3824C000, 0x3824E000, 0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825A000, 0x3825C000,
1327  0x3825E000, 0x38260000, 0x38262000, 0x38264000, 0x38266000, 0x38268000, 0x3826A000, 0x3826C000, 0x3826E000,
1328  0x38270000, 0x38272000, 0x38274000, 0x38276000, 0x38278000, 0x3827A000, 0x3827C000, 0x3827E000, 0x38280000,
1329  0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828A000, 0x3828C000, 0x3828E000, 0x38290000, 0x38292000,
1330  0x38294000, 0x38296000, 0x38298000, 0x3829A000, 0x3829C000, 0x3829E000, 0x382A0000, 0x382A2000, 0x382A4000,
1331  0x382A6000, 0x382A8000, 0x382AA000, 0x382AC000, 0x382AE000, 0x382B0000, 0x382B2000, 0x382B4000, 0x382B6000,
1332  0x382B8000, 0x382BA000, 0x382BC000, 0x382BE000, 0x382C0000, 0x382C2000, 0x382C4000, 0x382C6000, 0x382C8000,
1333  0x382CA000, 0x382CC000, 0x382CE000, 0x382D0000, 0x382D2000, 0x382D4000, 0x382D6000, 0x382D8000, 0x382DA000,
1334  0x382DC000, 0x382DE000, 0x382E0000, 0x382E2000, 0x382E4000, 0x382E6000, 0x382E8000, 0x382EA000, 0x382EC000,
1335  0x382EE000, 0x382F0000, 0x382F2000, 0x382F4000, 0x382F6000, 0x382F8000, 0x382FA000, 0x382FC000, 0x382FE000,
1336  0x38300000, 0x38302000, 0x38304000, 0x38306000, 0x38308000, 0x3830A000, 0x3830C000, 0x3830E000, 0x38310000,
1337  0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831A000, 0x3831C000, 0x3831E000, 0x38320000, 0x38322000,
1338  0x38324000, 0x38326000, 0x38328000, 0x3832A000, 0x3832C000, 0x3832E000, 0x38330000, 0x38332000, 0x38334000,
1339  0x38336000, 0x38338000, 0x3833A000, 0x3833C000, 0x3833E000, 0x38340000, 0x38342000, 0x38344000, 0x38346000,
1340  0x38348000, 0x3834A000, 0x3834C000, 0x3834E000, 0x38350000, 0x38352000, 0x38354000, 0x38356000, 0x38358000,
1341  0x3835A000, 0x3835C000, 0x3835E000, 0x38360000, 0x38362000, 0x38364000, 0x38366000, 0x38368000, 0x3836A000,
1342  0x3836C000, 0x3836E000, 0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837A000, 0x3837C000,
1343  0x3837E000, 0x38380000, 0x38382000, 0x38384000, 0x38386000, 0x38388000, 0x3838A000, 0x3838C000, 0x3838E000,
1344  0x38390000, 0x38392000, 0x38394000, 0x38396000, 0x38398000, 0x3839A000, 0x3839C000, 0x3839E000, 0x383A0000,
1345  0x383A2000, 0x383A4000, 0x383A6000, 0x383A8000, 0x383AA000, 0x383AC000, 0x383AE000, 0x383B0000, 0x383B2000,
1346  0x383B4000, 0x383B6000, 0x383B8000, 0x383BA000, 0x383BC000, 0x383BE000, 0x383C0000, 0x383C2000, 0x383C4000,
1347  0x383C6000, 0x383C8000, 0x383CA000, 0x383CC000, 0x383CE000, 0x383D0000, 0x383D2000, 0x383D4000, 0x383D6000,
1348  0x383D8000, 0x383DA000, 0x383DC000, 0x383DE000, 0x383E0000, 0x383E2000, 0x383E4000, 0x383E6000, 0x383E8000,
1349  0x383EA000, 0x383EC000, 0x383EE000, 0x383F0000, 0x383F2000, 0x383F4000, 0x383F6000, 0x383F8000, 0x383FA000,
1350  0x383FC000, 0x383FE000, 0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840A000, 0x3840C000,
1351  0x3840E000, 0x38410000, 0x38412000, 0x38414000, 0x38416000, 0x38418000, 0x3841A000, 0x3841C000, 0x3841E000,
1352  0x38420000, 0x38422000, 0x38424000, 0x38426000, 0x38428000, 0x3842A000, 0x3842C000, 0x3842E000, 0x38430000,
1353  0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843A000, 0x3843C000, 0x3843E000, 0x38440000, 0x38442000,
1354  0x38444000, 0x38446000, 0x38448000, 0x3844A000, 0x3844C000, 0x3844E000, 0x38450000, 0x38452000, 0x38454000,
1355  0x38456000, 0x38458000, 0x3845A000, 0x3845C000, 0x3845E000, 0x38460000, 0x38462000, 0x38464000, 0x38466000,
1356  0x38468000, 0x3846A000, 0x3846C000, 0x3846E000, 0x38470000, 0x38472000, 0x38474000, 0x38476000, 0x38478000,
1357  0x3847A000, 0x3847C000, 0x3847E000, 0x38480000, 0x38482000, 0x38484000, 0x38486000, 0x38488000, 0x3848A000,
1358  0x3848C000, 0x3848E000, 0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849A000, 0x3849C000,
1359  0x3849E000, 0x384A0000, 0x384A2000, 0x384A4000, 0x384A6000, 0x384A8000, 0x384AA000, 0x384AC000, 0x384AE000,
1360  0x384B0000, 0x384B2000, 0x384B4000, 0x384B6000, 0x384B8000, 0x384BA000, 0x384BC000, 0x384BE000, 0x384C0000,
1361  0x384C2000, 0x384C4000, 0x384C6000, 0x384C8000, 0x384CA000, 0x384CC000, 0x384CE000, 0x384D0000, 0x384D2000,
1362  0x384D4000, 0x384D6000, 0x384D8000, 0x384DA000, 0x384DC000, 0x384DE000, 0x384E0000, 0x384E2000, 0x384E4000,
1363  0x384E6000, 0x384E8000, 0x384EA000, 0x384EC000, 0x384EE000, 0x384F0000, 0x384F2000, 0x384F4000, 0x384F6000,
1364  0x384F8000, 0x384FA000, 0x384FC000, 0x384FE000, 0x38500000, 0x38502000, 0x38504000, 0x38506000, 0x38508000,
1365  0x3850A000, 0x3850C000, 0x3850E000, 0x38510000, 0x38512000, 0x38514000, 0x38516000, 0x38518000, 0x3851A000,
1366  0x3851C000, 0x3851E000, 0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852A000, 0x3852C000,
1367  0x3852E000, 0x38530000, 0x38532000, 0x38534000, 0x38536000, 0x38538000, 0x3853A000, 0x3853C000, 0x3853E000,
1368  0x38540000, 0x38542000, 0x38544000, 0x38546000, 0x38548000, 0x3854A000, 0x3854C000, 0x3854E000, 0x38550000,
1369  0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855A000, 0x3855C000, 0x3855E000, 0x38560000, 0x38562000,
1370  0x38564000, 0x38566000, 0x38568000, 0x3856A000, 0x3856C000, 0x3856E000, 0x38570000, 0x38572000, 0x38574000,
1371  0x38576000, 0x38578000, 0x3857A000, 0x3857C000, 0x3857E000, 0x38580000, 0x38582000, 0x38584000, 0x38586000,
1372  0x38588000, 0x3858A000, 0x3858C000, 0x3858E000, 0x38590000, 0x38592000, 0x38594000, 0x38596000, 0x38598000,
1373  0x3859A000, 0x3859C000, 0x3859E000, 0x385A0000, 0x385A2000, 0x385A4000, 0x385A6000, 0x385A8000, 0x385AA000,
1374  0x385AC000, 0x385AE000, 0x385B0000, 0x385B2000, 0x385B4000, 0x385B6000, 0x385B8000, 0x385BA000, 0x385BC000,
1375  0x385BE000, 0x385C0000, 0x385C2000, 0x385C4000, 0x385C6000, 0x385C8000, 0x385CA000, 0x385CC000, 0x385CE000,
1376  0x385D0000, 0x385D2000, 0x385D4000, 0x385D6000, 0x385D8000, 0x385DA000, 0x385DC000, 0x385DE000, 0x385E0000,
1377  0x385E2000, 0x385E4000, 0x385E6000, 0x385E8000, 0x385EA000, 0x385EC000, 0x385EE000, 0x385F0000, 0x385F2000,
1378  0x385F4000, 0x385F6000, 0x385F8000, 0x385FA000, 0x385FC000, 0x385FE000, 0x38600000, 0x38602000, 0x38604000,
1379  0x38606000, 0x38608000, 0x3860A000, 0x3860C000, 0x3860E000, 0x38610000, 0x38612000, 0x38614000, 0x38616000,
1380  0x38618000, 0x3861A000, 0x3861C000, 0x3861E000, 0x38620000, 0x38622000, 0x38624000, 0x38626000, 0x38628000,
1381  0x3862A000, 0x3862C000, 0x3862E000, 0x38630000, 0x38632000, 0x38634000, 0x38636000, 0x38638000, 0x3863A000,
1382  0x3863C000, 0x3863E000, 0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864A000, 0x3864C000,
1383  0x3864E000, 0x38650000, 0x38652000, 0x38654000, 0x38656000, 0x38658000, 0x3865A000, 0x3865C000, 0x3865E000,
1384  0x38660000, 0x38662000, 0x38664000, 0x38666000, 0x38668000, 0x3866A000, 0x3866C000, 0x3866E000, 0x38670000,
1385  0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867A000, 0x3867C000, 0x3867E000, 0x38680000, 0x38682000,
1386  0x38684000, 0x38686000, 0x38688000, 0x3868A000, 0x3868C000, 0x3868E000, 0x38690000, 0x38692000, 0x38694000,
1387  0x38696000, 0x38698000, 0x3869A000, 0x3869C000, 0x3869E000, 0x386A0000, 0x386A2000, 0x386A4000, 0x386A6000,
1388  0x386A8000, 0x386AA000, 0x386AC000, 0x386AE000, 0x386B0000, 0x386B2000, 0x386B4000, 0x386B6000, 0x386B8000,
1389  0x386BA000, 0x386BC000, 0x386BE000, 0x386C0000, 0x386C2000, 0x386C4000, 0x386C6000, 0x386C8000, 0x386CA000,
1390  0x386CC000, 0x386CE000, 0x386D0000, 0x386D2000, 0x386D4000, 0x386D6000, 0x386D8000, 0x386DA000, 0x386DC000,
1391  0x386DE000, 0x386E0000, 0x386E2000, 0x386E4000, 0x386E6000, 0x386E8000, 0x386EA000, 0x386EC000, 0x386EE000,
1392  0x386F0000, 0x386F2000, 0x386F4000, 0x386F6000, 0x386F8000, 0x386FA000, 0x386FC000, 0x386FE000, 0x38700000,
1393  0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870A000, 0x3870C000, 0x3870E000, 0x38710000, 0x38712000,
1394  0x38714000, 0x38716000, 0x38718000, 0x3871A000, 0x3871C000, 0x3871E000, 0x38720000, 0x38722000, 0x38724000,
1395  0x38726000, 0x38728000, 0x3872A000, 0x3872C000, 0x3872E000, 0x38730000, 0x38732000, 0x38734000, 0x38736000,
1396  0x38738000, 0x3873A000, 0x3873C000, 0x3873E000, 0x38740000, 0x38742000, 0x38744000, 0x38746000, 0x38748000,
1397  0x3874A000, 0x3874C000, 0x3874E000, 0x38750000, 0x38752000, 0x38754000, 0x38756000, 0x38758000, 0x3875A000,
1398  0x3875C000, 0x3875E000, 0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876A000, 0x3876C000,
1399  0x3876E000, 0x38770000, 0x38772000, 0x38774000, 0x38776000, 0x38778000, 0x3877A000, 0x3877C000, 0x3877E000,
1400  0x38780000, 0x38782000, 0x38784000, 0x38786000, 0x38788000, 0x3878A000, 0x3878C000, 0x3878E000, 0x38790000,
1401  0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879A000, 0x3879C000, 0x3879E000, 0x387A0000, 0x387A2000,
1402  0x387A4000, 0x387A6000, 0x387A8000, 0x387AA000, 0x387AC000, 0x387AE000, 0x387B0000, 0x387B2000, 0x387B4000,
1403  0x387B6000, 0x387B8000, 0x387BA000, 0x387BC000, 0x387BE000, 0x387C0000, 0x387C2000, 0x387C4000, 0x387C6000,
1404  0x387C8000, 0x387CA000, 0x387CC000, 0x387CE000, 0x387D0000, 0x387D2000, 0x387D4000, 0x387D6000, 0x387D8000,
1405  0x387DA000, 0x387DC000, 0x387DE000, 0x387E0000, 0x387E2000, 0x387E4000, 0x387E6000, 0x387E8000, 0x387EA000,
1406  0x387EC000, 0x387EE000, 0x387F0000, 0x387F2000, 0x387F4000, 0x387F6000, 0x387F8000, 0x387FA000, 0x387FC000,
1407  0x387FE000 };
1408  static const bits<float>::type exponent_table[64] = { 0x00000000, 0x00800000, 0x01000000, 0x01800000,
1409  0x02000000, 0x02800000, 0x03000000, 0x03800000, 0x04000000, 0x04800000, 0x05000000, 0x05800000, 0x06000000,
1410  0x06800000, 0x07000000, 0x07800000, 0x08000000, 0x08800000, 0x09000000, 0x09800000, 0x0A000000, 0x0A800000,
1411  0x0B000000, 0x0B800000, 0x0C000000, 0x0C800000, 0x0D000000, 0x0D800000, 0x0E000000, 0x0E800000, 0x0F000000,
1412  0x47800000, 0x80000000, 0x80800000, 0x81000000, 0x81800000, 0x82000000, 0x82800000, 0x83000000, 0x83800000,
1413  0x84000000, 0x84800000, 0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000, 0x88000000,
1414  0x88800000, 0x89000000, 0x89800000, 0x8A000000, 0x8A800000, 0x8B000000, 0x8B800000, 0x8C000000, 0x8C800000,
1415  0x8D000000, 0x8D800000, 0x8E000000, 0x8E800000, 0x8F000000, 0xC7800000 };
1416  static const unsigned short offset_table[64] = { 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1417  1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1418  1024, 1024, 1024, 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1419  1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024 };
1420  bits<float>::type fbits =
1421  mantissa_table[offset_table[value >> 10] + (value & 0x3FF)] + exponent_table[value >> 10];
1422 #endif
1423  float out;
1424  std::memcpy(&out, &fbits, sizeof(float));
1425  return out;
1426 #endif
1427  }
1428 
1432  inline double half2float_impl(unsigned int value, double, true_type)
1433  {
1434 #if HALF_ENABLE_F16C_INTRINSICS
1435  return _mm_cvtsd_f64(_mm_cvtps_pd(_mm_cvtph_ps(_mm_cvtsi32_si128(value))));
1436 #else
1437  uint32 hi = static_cast<uint32>(value & 0x8000) << 16;
1438  unsigned int abs = value & 0x7FFF;
1439  if (abs) {
1440  hi |= 0x3F000000 << static_cast<unsigned>(abs >= 0x7C00);
1441  for (; abs < 0x400; abs <<= 1, hi -= 0x100000)
1442  ;
1443  hi += static_cast<uint32>(abs) << 10;
1444  }
1445  bits<double>::type dbits = static_cast<bits<double>::type>(hi) << 32;
1446  double out;
1447  std::memcpy(&out, &dbits, sizeof(double));
1448  return out;
1449 #endif
1450  }
1451 
1456  template <typename T> T half2float_impl(unsigned int value, T, ...)
1457  {
1458  T out;
1459  unsigned int abs = value & 0x7FFF;
1460  if (abs > 0x7C00)
1461  out = (std::numeric_limits<T>::has_signaling_NaN && !(abs & 0x200))
1462  ? std::numeric_limits<T>::signaling_NaN()
1463  : std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN()
1464  : T();
1465  else if (abs == 0x7C00)
1466  out = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity()
1467  : std::numeric_limits<T>::max();
1468  else if (abs > 0x3FF)
1469  out = std::ldexp(static_cast<T>((abs & 0x3FF) | 0x400), (abs >> 10) - 25);
1470  else
1471  out = std::ldexp(static_cast<T>(abs), -24);
1472  return (value & 0x8000) ? -out : out;
1473  }
1474 
1479  template <typename T> T half2float(unsigned int value)
1480  {
1481  return half2float_impl(value, T(),
1482  bool_type < std::numeric_limits<T>::is_iec559 && sizeof(typename bits<T>::type) == sizeof(T) > ());
1483  }
1484 
1492  template <std::float_round_style R, bool E, bool I, typename T> T half2int(unsigned int value)
1493  {
1494  unsigned int abs = value & 0x7FFF;
1495  if (abs >= 0x7C00) {
1496  raise(FE_INVALID);
1497  return (value & 0x8000) ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
1498  }
1499  if (abs < 0x3800) {
1500  raise(FE_INEXACT, I);
1501  return (R == std::round_toward_infinity) ? T(~(value >> 15) & (abs != 0))
1502  : (R == std::round_toward_neg_infinity) ? -T(value > 0x8000)
1503  : T();
1504  }
1505  int exp = 25 - (abs >> 10);
1506  unsigned int m = (value & 0x3FF) | 0x400;
1507  int32 i = static_cast<int32>((exp <= 0)
1508  ? (m << -exp)
1509  : ((m +
1510  ((R == std::round_to_nearest) ? ((1 << (exp - 1)) - (~(m >> exp) & E))
1511  : (R == std::round_toward_infinity) ? (((1 << exp) - 1) & ((value >> 15) - 1))
1512  : (R == std::round_toward_neg_infinity) ? (((1 << exp) - 1) & -(value >> 15))
1513  : 0)) >>
1514  exp));
1515  if ((!std::numeric_limits<T>::is_signed && (value & 0x8000)) ||
1516  (std::numeric_limits<T>::digits < 16 &&
1517  ((value & 0x8000) ? (-i < std::numeric_limits<T>::min()) : (i > std::numeric_limits<T>::max()))))
1518  raise(FE_INVALID);
1519  else if (I && exp > 0 && (m & ((1 << exp) - 1)))
1520  raise(FE_INEXACT);
1521  return static_cast<T>((value & 0x8000) ? -i : i);
1522  }
1523 
1527 
1533  template <std::float_round_style R> uint32 mulhi(uint32 x, uint32 y)
1534  {
1535  uint32 xy = (x >> 16) * (y & 0xFFFF), yx = (x & 0xFFFF) * (y >> 16),
1536  c = (xy & 0xFFFF) + (yx & 0xFFFF) + (((x & 0xFFFF) * (y & 0xFFFF)) >> 16);
1537  return (x >> 16) * (y >> 16) + (xy >> 16) + (yx >> 16) + (c >> 16) +
1538  ((R == std::round_to_nearest) ? ((c >> 15) & 1)
1539  : (R == std::round_toward_infinity) ? ((c & 0xFFFF) != 0)
1540  : 0);
1541  }
1542 
1548  {
1549 #if HALF_ENABLE_CPP11_LONG_LONG
1550  return static_cast<uint32>(
1551  (static_cast<unsigned long long>(x) * static_cast<unsigned long long>(y) + 0x80000000) >> 32);
1552 #else
1553  return mulhi<std::round_to_nearest>(x, y);
1554 #endif
1555  }
1556 
1562  inline uint32 divide64(uint32 x, uint32 y, int& s)
1563  {
1564 #if HALF_ENABLE_CPP11_LONG_LONG
1565  unsigned long long xx = static_cast<unsigned long long>(x) << 32;
1566  return s = (xx % y != 0), static_cast<uint32>(xx / y);
1567 #else
1568  y >>= 1;
1569  uint32 rem = x, div = 0;
1570  for (unsigned int i = 0; i < 32; ++i) {
1571  div <<= 1;
1572  if (rem >= y) {
1573  rem -= y;
1574  div |= 1;
1575  }
1576  rem <<= 1;
1577  }
1578  return s = rem > 1, div;
1579 #endif
1580  }
1581 
1589  template <bool Q, bool R> unsigned int mod(unsigned int x, unsigned int y, int* quo = NULL)
1590  {
1591  unsigned int q = 0;
1592  if (x > y) {
1593  int absx = x, absy = y, expx = 0, expy = 0;
1594  for (; absx < 0x400; absx <<= 1, --expx)
1595  ;
1596  for (; absy < 0x400; absy <<= 1, --expy)
1597  ;
1598  expx += absx >> 10;
1599  expy += absy >> 10;
1600  int mx = (absx & 0x3FF) | 0x400, my = (absy & 0x3FF) | 0x400;
1601  for (int d = expx - expy; d; --d) {
1602  if (!Q && mx == my)
1603  return 0;
1604  if (mx >= my) {
1605  mx -= my;
1606  q += Q;
1607  }
1608  mx <<= 1;
1609  q <<= static_cast<int>(Q);
1610  }
1611  if (!Q && mx == my)
1612  return 0;
1613  if (mx >= my) {
1614  mx -= my;
1615  ++q;
1616  }
1617  if (Q) {
1618  q &= (1 << (std::numeric_limits<int>::digits - 1)) - 1;
1619  if (!mx)
1620  return *quo = q, 0;
1621  }
1622  for (; mx < 0x400; mx <<= 1, --expy)
1623  ;
1624  x = (expy > 0) ? ((expy << 10) | (mx & 0x3FF)) : (mx >> (1 - expy));
1625  }
1626  if (R) {
1627  unsigned int a, b;
1628  if (y < 0x800) {
1629  a = (x < 0x400) ? (x << 1) : (x + 0x400);
1630  b = y;
1631  } else {
1632  a = x;
1633  b = y - 0x400;
1634  }
1635  if (a > b || (a == b && (q & 1))) {
1636  int exp = (y >> 10) + (y <= 0x3FF), d = exp - (x >> 10) - (x <= 0x3FF);
1637  int m = (((y & 0x3FF) | ((y > 0x3FF) << 10)) << 1) - (((x & 0x3FF) | ((x > 0x3FF) << 10)) << (1 - d));
1638  for (; m < 0x800 && exp > 1; m <<= 1, --exp)
1639  ;
1640  x = 0x8000 + ((exp - 1) << 10) + (m >> 1);
1641  q += Q;
1642  }
1643  }
1644  if (Q)
1645  *quo = q;
1646  return x;
1647  }
1648 
1654  template <unsigned int F> uint32 sqrt(uint32& r, int& exp)
1655  {
1656  int i = exp & 1;
1657  r <<= i;
1658  exp = (exp - i) / 2;
1659  uint32 m = 0;
1660  for (uint32 bit = static_cast<uint32>(1) << F; bit; bit >>= 2) {
1661  if (r < m + bit)
1662  m >>= 1;
1663  else {
1664  r -= m + bit;
1665  m = (m >> 1) + bit;
1666  }
1667  }
1668  return m;
1669  }
1670 
1676  inline uint32 exp2(uint32 m, unsigned int n = 32)
1677  {
1678  static const uint32 logs[] = { 0x80000000, 0x4AE00D1D, 0x2934F098, 0x15C01A3A, 0x0B31FB7D, 0x05AEB4DD,
1679  0x02DCF2D1, 0x016FE50B, 0x00B84E23, 0x005C3E10, 0x002E24CA, 0x001713D6, 0x000B8A47, 0x0005C53B, 0x0002E2A3,
1680  0x00017153, 0x0000B8AA, 0x00005C55, 0x00002E2B, 0x00001715, 0x00000B8B, 0x000005C5, 0x000002E3, 0x00000171,
1681  0x000000B9, 0x0000005C, 0x0000002E, 0x00000017, 0x0000000C, 0x00000006, 0x00000003, 0x00000001 };
1682  if (!m)
1683  return 0x80000000;
1684  uint32 mx = 0x80000000, my = 0;
1685  for (unsigned int i = 1; i < n; ++i) {
1686  uint32 mz = my + logs[i];
1687  if (mz <= m) {
1688  my = mz;
1689  mx += mx >> i;
1690  }
1691  }
1692  return mx;
1693  }
1694 
1700  inline uint32 log2(uint32 m, unsigned int n = 32)
1701  {
1702  static const uint32 logs[] = { 0x80000000, 0x4AE00D1D, 0x2934F098, 0x15C01A3A, 0x0B31FB7D, 0x05AEB4DD,
1703  0x02DCF2D1, 0x016FE50B, 0x00B84E23, 0x005C3E10, 0x002E24CA, 0x001713D6, 0x000B8A47, 0x0005C53B, 0x0002E2A3,
1704  0x00017153, 0x0000B8AA, 0x00005C55, 0x00002E2B, 0x00001715, 0x00000B8B, 0x000005C5, 0x000002E3, 0x00000171,
1705  0x000000B9, 0x0000005C, 0x0000002E, 0x00000017, 0x0000000C, 0x00000006, 0x00000003, 0x00000001 };
1706  if (m == 0x40000000)
1707  return 0;
1708  uint32 mx = 0x40000000, my = 0;
1709  for (unsigned int i = 1; i < n; ++i) {
1710  uint32 mz = mx + (mx >> i);
1711  if (mz <= m) {
1712  mx = mz;
1713  my += logs[i];
1714  }
1715  }
1716  return my;
1717  }
1718 
1724  inline std::pair<uint32, uint32> sincos(uint32 mz, unsigned int n = 31)
1725  {
1726  static const uint32 angles[] = { 0x3243F6A9, 0x1DAC6705, 0x0FADBAFD, 0x07F56EA7, 0x03FEAB77, 0x01FFD55C,
1727  0x00FFFAAB, 0x007FFF55, 0x003FFFEB, 0x001FFFFD, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
1728  0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080,
1729  0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001 };
1730  uint32 mx = 0x26DD3B6A, my = 0;
1731  for (unsigned int i = 0; i < n; ++i) {
1732  uint32 sign = sign_mask(mz);
1733  uint32 tx = mx - (arithmetic_shift(my, i) ^ sign) + sign;
1734  uint32 ty = my + (arithmetic_shift(mx, i) ^ sign) - sign;
1735  mx = tx;
1736  my = ty;
1737  mz -= (angles[i] ^ sign) - sign;
1738  }
1739  return std::make_pair(my, mx);
1740  }
1741 
1748  inline uint32 atan2(uint32 my, uint32 mx, unsigned int n = 31)
1749  {
1750  static const uint32 angles[] = { 0x3243F6A9, 0x1DAC6705, 0x0FADBAFD, 0x07F56EA7, 0x03FEAB77, 0x01FFD55C,
1751  0x00FFFAAB, 0x007FFF55, 0x003FFFEB, 0x001FFFFD, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000,
1752  0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080,
1753  0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001 };
1754  uint32 mz = 0;
1755  for (unsigned int i = 0; i < n; ++i) {
1756  uint32 sign = sign_mask(my);
1757  uint32 tx = mx + (arithmetic_shift(my, i) ^ sign) - sign;
1758  uint32 ty = my - (arithmetic_shift(mx, i) ^ sign) + sign;
1759  mx = tx;
1760  my = ty;
1761  mz += (angles[i] ^ sign) - sign;
1762  }
1763  return mz;
1764  }
1765 
1770  inline uint32 angle_arg(unsigned int abs, int& k)
1771  {
1772  uint32 m = (abs & 0x3FF) | ((abs > 0x3FF) << 10);
1773  int exp = (abs >> 10) + (abs <= 0x3FF) - 15;
1774  if (abs < 0x3A48)
1775  return k = 0, m << (exp + 20);
1776 #if HALF_ENABLE_CPP11_LONG_LONG
1777  unsigned long long y = m * 0xA2F9836E4E442, mask = (1ULL << (62 - exp)) - 1, yi = (y + (mask >> 1)) & ~mask,
1778  f = y - yi;
1779  uint32 sign = -static_cast<uint32>(f >> 63);
1780  k = static_cast<int>(yi >> (62 - exp));
1781  return (multiply64(static_cast<uint32>((sign ? -f : f) >> (31 - exp)), 0xC90FDAA2) ^ sign) - sign;
1782 #else
1783  uint32 yh = m * 0xA2F98 + mulhi<std::round_toward_zero>(m, 0x36E4E442), yl = (m * 0x36E4E442) & 0xFFFFFFFF;
1784  uint32 mask = (static_cast<uint32>(1) << (30 - exp)) - 1, yi = (yh + (mask >> 1)) & ~mask,
1785  sign = -static_cast<uint32>(yi > yh);
1786  k = static_cast<int>(yi >> (30 - exp));
1787  uint32 fh = (yh ^ sign) + (yi ^ ~sign) - ~sign, fl = (yl ^ sign) - sign;
1788  return (multiply64((exp > -1) ? (((fh << (1 + exp)) & 0xFFFFFFFF) | ((fl & 0xFFFFFFFF) >> (31 - exp))) : fh,
1789  0xC90FDAA2) ^
1790  sign) -
1791  sign;
1792 #endif
1793  }
1794 
1798  inline std::pair<uint32, uint32> atan2_args(unsigned int abs)
1799  {
1800  int exp = -15;
1801  for (; abs < 0x400; abs <<= 1, --exp)
1802  ;
1803  exp += abs >> 10;
1804  uint32 my = ((abs & 0x3FF) | 0x400) << 5, r = my * my;
1805  int rexp = 2 * exp;
1806  r = 0x40000000 - ((rexp > -31) ? ((r >> -rexp) | ((r & ((static_cast<uint32>(1) << -rexp) - 1)) != 0)) : 1);
1807  for (rexp = 0; r < 0x40000000; r <<= 1, --rexp)
1808  ;
1809  uint32 mx = sqrt<30>(r, rexp);
1810  int d = exp - rexp;
1811  if (d < 0)
1812  return std::make_pair((d < -14) ? ((my >> (-d - 14)) + ((my >> (-d - 15)) & 1)) : (my << (14 + d)),
1813  (mx << 14) + (r << 13) / mx);
1814  if (d > 0)
1815  return std::make_pair(my << 14,
1816  (d > 14) ? ((mx >> (d - 14)) + ((mx >> (d - 15)) & 1))
1817  : ((d == 14) ? mx : ((mx << (14 - d)) + (r << (13 - d)) / mx)));
1818  return std::make_pair(my << 13, (mx << 13) + (r << 12) / mx);
1819  }
1820 
1826  inline std::pair<uint32, uint32> hyperbolic_args(unsigned int abs, int& exp, unsigned int n = 32)
1827  {
1828  uint32 mx = detail::multiply64(static_cast<uint32>((abs & 0x3FF) + ((abs > 0x3FF) << 10)) << 21, 0xB8AA3B29),
1829  my;
1830  int e = (abs >> 10) + (abs <= 0x3FF);
1831  if (e < 14) {
1832  exp = 0;
1833  mx >>= 14 - e;
1834  } else {
1835  exp = mx >> (45 - e);
1836  mx = (mx << (e - 14)) & 0x7FFFFFFF;
1837  }
1838  mx = exp2(mx, n);
1839  int d = exp << 1, s;
1840  if (mx > 0x80000000) {
1841  my = divide64(0x80000000, mx, s);
1842  my |= s;
1843  ++d;
1844  } else
1845  my = mx;
1846  return std::make_pair(mx, (d < 31) ? ((my >> d) | ((my & ((static_cast<uint32>(1) << d) - 1)) != 0)) : 1);
1847  }
1848 
1860  template <std::float_round_style R>
1861  unsigned int exp2_post(uint32 m, int exp, bool esign, unsigned int sign = 0, unsigned int n = 32)
1862  {
1863  if (esign) {
1864  exp = -exp - (m != 0);
1865  if (exp < -25)
1866  return underflow<R>(sign);
1867  else if (exp == -25)
1868  return rounded<R, false>(sign, 1, m != 0);
1869  } else if (exp > 15)
1870  return overflow<R>(sign);
1871  if (!m)
1872  return sign | (((exp += 15) > 0) ? (exp << 10) : check_underflow(0x200 >> -exp));
1873  m = exp2(m, n);
1874  int s = 0;
1875  if (esign)
1876  m = divide64(0x80000000, m, s);
1877  return fixed2half<R, 31, false, false, true>(m, exp + 14, sign, s);
1878  }
1879 
1891  template <std::float_round_style R, uint32 L>
1892  unsigned int log2_post(uint32 m, int ilog, int exp, unsigned int sign = 0)
1893  {
1894  uint32 msign = sign_mask(ilog);
1895  m = (((static_cast<uint32>(ilog) << 27) + (m >> 4)) ^ msign) - msign;
1896  if (!m)
1897  return 0;
1898  for (; m < 0x80000000; m <<= 1, --exp)
1899  ;
1900  int i = m >= L, s;
1901  exp += i;
1902  m >>= 1 + i;
1903  sign ^= msign & 0x8000;
1904  if (exp < -11)
1905  return underflow<R>(sign);
1906  m = divide64(m, L, s);
1907  return fixed2half<R, 30, false, false, true>(m, exp, sign, 1);
1908  }
1909 
1918  template <std::float_round_style R> unsigned int hypot_post(uint32 r, int exp)
1919  {
1920  int i = r >> 31;
1921  if ((exp += i) > 46)
1922  return overflow<R>();
1923  if (exp < -34)
1924  return underflow<R>();
1925  r = (r >> i) | (r & i);
1926  uint32 m = sqrt<30>(r, exp += 15);
1927  return fixed2half<R, 15, false, false, false>(m, exp - 1, 0, r != 0);
1928  }
1929 
1940  template <std::float_round_style R> unsigned int tangent_post(uint32 my, uint32 mx, int exp, unsigned int sign = 0)
1941  {
1942  int i = my >= mx, s;
1943  exp += i;
1944  if (exp > 29)
1945  return overflow<R>(sign);
1946  if (exp < -11)
1947  return underflow<R>(sign);
1948  uint32 m = divide64(my >> (i + 1), mx, s);
1949  return fixed2half<R, 30, false, false, true>(m, exp, sign, s);
1950  }
1951 
1961  template <std::float_round_style R, bool S> unsigned int area(unsigned int arg)
1962  {
1963  int abs = arg & 0x7FFF, expx = (abs >> 10) + (abs <= 0x3FF) - 15, expy = -15, ilog, i;
1964  uint32 mx = static_cast<uint32>((abs & 0x3FF) | ((abs > 0x3FF) << 10)) << 20, my, r;
1965  for (; abs < 0x400; abs <<= 1, --expy)
1966  ;
1967  expy += abs >> 10;
1968  r = ((abs & 0x3FF) | 0x400) << 5;
1969  r *= r;
1970  i = r >> 31;
1971  expy = 2 * expy + i;
1972  r >>= i;
1973  if (S) {
1974  if (expy < 0) {
1975  r = 0x40000000 +
1976  ((expy > -30) ? ((r >> -expy) | ((r & ((static_cast<uint32>(1) << -expy) - 1)) != 0)) : 1);
1977  expy = 0;
1978  } else {
1979  r += 0x40000000 >> expy;
1980  i = r >> 31;
1981  r = (r >> i) | (r & i);
1982  expy += i;
1983  }
1984  } else {
1985  r -= 0x40000000 >> expy;
1986  for (; r < 0x40000000; r <<= 1, --expy)
1987  ;
1988  }
1989  my = sqrt<30>(r, expy);
1990  my = (my << 15) + (r << 14) / my;
1991  if (S) {
1992  mx >>= expy - expx;
1993  ilog = expy;
1994  } else {
1995  my >>= expx - expy;
1996  ilog = expx;
1997  }
1998  my += mx;
1999  i = my >> 31;
2000  static const int G = S && (R == std::round_to_nearest);
2001  return log2_post<R, 0xB8AA3B2A>(
2002  log2(my >> i, 26 + S + G) + (G << 3), ilog + i, 17, arg & (static_cast<unsigned>(S) << 15));
2003  }
2004 
2006  struct f31 {
2011  : m(mant)
2012  , exp(e)
2013  {
2014  }
2015 
2018  f31(unsigned int abs)
2019  : exp(-15)
2020  {
2021  for (; abs < 0x400; abs <<= 1, --exp)
2022  ;
2023  m = static_cast<uint32>((abs & 0x3FF) | 0x400) << 21;
2024  exp += (abs >> 10);
2025  }
2026 
2031  friend f31 operator+(f31 a, f31 b)
2032  {
2033  if (b.exp > a.exp)
2034  std::swap(a, b);
2035  int d = a.exp - b.exp;
2036  uint32 m = a.m + ((d < 32) ? (b.m >> d) : 0);
2037  int i = (m & 0xFFFFFFFF) < a.m;
2038  return f31(((m + i) >> i) | 0x80000000, a.exp + i);
2039  }
2040 
2045  friend f31 operator-(f31 a, f31 b)
2046  {
2047  int d = a.exp - b.exp, exp = a.exp;
2048  uint32 m = a.m - ((d < 32) ? (b.m >> d) : 0);
2049  if (!m)
2050  return f31(0, -32);
2051  for (; m < 0x80000000; m <<= 1, --exp)
2052  ;
2053  return f31(m, exp);
2054  }
2055 
2060  friend f31 operator*(f31 a, f31 b)
2061  {
2062  uint32 m = multiply64(a.m, b.m);
2063  int i = m >> 31;
2064  return f31(m << (1 - i), a.exp + b.exp + i);
2065  }
2066 
2071  friend f31 operator/(f31 a, f31 b)
2072  {
2073  int i = a.m >= b.m, s;
2074  uint32 m = divide64((a.m + i) >> i, b.m, s);
2075  return f31(m, a.exp - b.exp + i - 1);
2076  }
2077 
2079  int exp;
2080  };
2081 
2092  template <std::float_round_style R, bool C> unsigned int erf(unsigned int arg)
2093  {
2094  unsigned int abs = arg & 0x7FFF, sign = arg & 0x8000;
2095  f31 x(abs), x2 = x * x * f31(0xB8AA3B29, 0),
2096  t = f31(0x80000000, 0) / (f31(0x80000000, 0) + f31(0xA7BA054A, -2) * x), t2 = t * t;
2097  f31 e = ((f31(0x87DC2213, 0) * t2 + f31(0xB5F0E2AE, 0)) * t2 + f31(0x82790637, -2) -
2098  (f31(0xBA00E2B8, 0) * t2 + f31(0x91A98E62, -2)) * t) *
2099  t /
2100  ((x2.exp < 0) ? f31(exp2((x2.exp > -32) ? (x2.m >> -x2.exp) : 0, 30), 0)
2101  : f31(exp2((x2.m << x2.exp) & 0x7FFFFFFF, 22), x2.m >> (31 - x2.exp)));
2102  return (!C || sign)
2103  ? fixed2half<R, 31, false, true, true>(0x80000000 - (e.m >> (C - e.exp)), 14 + C, sign & (C - 1U))
2104  : (e.exp < -25) ? underflow<R>()
2105  : fixed2half<R, 30, false, false, true>(e.m >> 1, e.exp + 14, 0, e.m & 1);
2106  }
2107 
2117  template <std::float_round_style R, bool L> unsigned int gamma(unsigned int arg)
2118  {
2119  /* static const double p[] ={ 2.50662827563479526904, 225.525584619175212544,
2120  -268.295973841304927459, 80.9030806934622512966, -5.00757863970517583837, 0.0114684895434781459556 }; double
2121  t = arg + 4.65, s = p[0]; for(unsigned int i=0; i<5; ++i) s += p[i+1] / (arg+i); return std::log(s) +
2122  (arg-0.5)*std::log(t) - t;
2123  */
2124  static const f31 pi(0xC90FDAA2, 1), lbe(0xB8AA3B29, 0);
2125  unsigned int abs = arg & 0x7FFF, sign = arg & 0x8000;
2126  bool bsign = sign != 0;
2127  f31 z(abs), x = sign ? (z + f31(0x80000000, 0)) : z, t = x + f31(0x94CCCCCD, 2),
2128  s = f31(0xA06C9901, 1) + f31(0xBBE654E2, -7) / (x + f31(0x80000000, 2)) +
2129  f31(0xA1CE6098, 6) / (x + f31(0x80000000, 1)) + f31(0xE1868CB7, 7) / x -
2130  f31(0x8625E279, 8) / (x + f31(0x80000000, 0)) - f31(0xA03E158F, 2) / (x + f31(0xC0000000, 1));
2131  int i = (s.exp >= 2) + (s.exp >= 4) + (s.exp >= 8) + (s.exp >= 16);
2132  s = f31((static_cast<uint32>(s.exp) << (31 - i)) + (log2(s.m >> 1, 28) >> i), i) / lbe;
2133  if (x.exp != -1 || x.m != 0x80000000) {
2134  i = (t.exp >= 2) + (t.exp >= 4) + (t.exp >= 8);
2135  f31 l = f31((static_cast<uint32>(t.exp) << (31 - i)) + (log2(t.m >> 1, 30) >> i), i) / lbe;
2136  s = (x.exp < -1) ? (s - (f31(0x80000000, -1) - x) * l) : (s + (x - f31(0x80000000, -1)) * l);
2137  }
2138  s = x.exp ? (s - t) : (t - s);
2139  if (bsign) {
2140  if (z.exp >= 0) {
2141  sign &= (L | ((z.m >> (31 - z.exp)) & 1)) - 1;
2142  for (z = f31((z.m << (1 + z.exp)) & 0xFFFFFFFF, -1); z.m < 0x80000000; z.m <<= 1, --z.exp)
2143  ;
2144  }
2145  if (z.exp == -1)
2146  z = f31(0x80000000, 0) - z;
2147  if (z.exp < -1) {
2148  z = z * pi;
2149  z.m = sincos(z.m >> (1 - z.exp), 30).first;
2150  for (z.exp = 1; z.m < 0x80000000; z.m <<= 1, --z.exp)
2151  ;
2152  } else
2153  z = f31(0x80000000, 0);
2154  }
2155  if (L) {
2156  if (bsign) {
2157  f31 l(0x92868247, 0);
2158  if (z.exp < 0) {
2159  uint32 m = log2((z.m + 1) >> 1, 27);
2160  z = f31(-((static_cast<uint32>(z.exp) << 26) + (m >> 5)), 5);
2161  for (; z.m < 0x80000000; z.m <<= 1, --z.exp)
2162  ;
2163  l = l + z / lbe;
2164  }
2165  sign = static_cast<unsigned>(x.exp && (l.exp < s.exp || (l.exp == s.exp && l.m < s.m))) << 15;
2166  s = sign ? (s - l) : x.exp ? (l - s) : (l + s);
2167  } else {
2168  sign = static_cast<unsigned>(x.exp == 0) << 15;
2169  if (s.exp < -24)
2170  return underflow<R>(sign);
2171  if (s.exp > 15)
2172  return overflow<R>(sign);
2173  }
2174  } else {
2175  s = s * lbe;
2176  uint32 m;
2177  if (s.exp < 0) {
2178  m = s.m >> -s.exp;
2179  s.exp = 0;
2180  } else {
2181  m = (s.m << s.exp) & 0x7FFFFFFF;
2182  s.exp = (s.m >> (31 - s.exp));
2183  }
2184  s.m = exp2(m, 27);
2185  if (!x.exp)
2186  s = f31(0x80000000, 0) / s;
2187  if (bsign) {
2188  if (z.exp < 0)
2189  s = s * z;
2190  s = pi / s;
2191  if (s.exp < -24)
2192  return underflow<R>(sign);
2193  } else if (z.exp > 0 && !(z.m & ((1 << (31 - z.exp)) - 1)))
2194  return ((s.exp + 14) << 10) + (s.m >> 21);
2195  if (s.exp > 15)
2196  return overflow<R>(sign);
2197  }
2198  return fixed2half<R, 31, false, false, true>(s.m, s.exp + 14, sign);
2199  }
2201 
2202  template <typename, typename, std::float_round_style> struct half_caster;
2203 } // namespace detail
2204 
2222 class half {
2223 public:
2226 
2231 
2235  explicit half(float rhs)
2236  : data_(static_cast<detail::uint16>(detail::float2half<round_style>(rhs)))
2237  {
2238  }
2239 
2242  operator float() const { return detail::half2float<float>(data_); }
2243 
2248  half& operator=(float rhs)
2249  {
2250  data_ = static_cast<detail::uint16>(detail::float2half<round_style>(rhs));
2251  return *this;
2252  }
2253 
2257 
2263  half& operator+=(half rhs) { return *this = *this + rhs; }
2264 
2270  half& operator-=(half rhs) { return *this = *this - rhs; }
2271 
2277  half& operator*=(half rhs) { return *this = *this * rhs; }
2278 
2284  half& operator/=(half rhs) { return *this = *this / rhs; }
2285 
2290  half& operator+=(float rhs) { return *this = *this + rhs; }
2291 
2296  half& operator-=(float rhs) { return *this = *this - rhs; }
2297 
2302  half& operator*=(float rhs) { return *this = *this * rhs; }
2303 
2308  half& operator/=(float rhs) { return *this = *this / rhs; }
2309 
2313 
2317  half& operator++() { return *this = *this + half(detail::binary, 0x3C00); }
2318 
2322  half& operator--() { return *this = *this + half(detail::binary, 0xBC00); }
2323 
2328  {
2329  half out(*this);
2330  ++*this;
2331  return out;
2332  }
2333 
2338  {
2339  half out(*this);
2340  --*this;
2341  return out;
2342  }
2344 
2345 private:
2347  static const std::float_round_style round_style = (std::float_round_style)(HALF_ROUND_STYLE);
2348 
2351  HALF_CONSTEXPR half(detail::binary_t, unsigned int bits) HALF_NOEXCEPT : data_(static_cast<detail::uint16>(bits)) {}
2352 
2355 
2356 #ifndef HALF_DOXYGEN_ONLY
2357  friend HALF_CONSTEXPR_NOERR bool operator==(half, half);
2358  friend HALF_CONSTEXPR_NOERR bool operator!=(half, half);
2359  friend HALF_CONSTEXPR_NOERR bool operator<(half, half);
2360  friend HALF_CONSTEXPR_NOERR bool operator>(half, half);
2361  friend HALF_CONSTEXPR_NOERR bool operator<=(half, half);
2362  friend HALF_CONSTEXPR_NOERR bool operator>=(half, half);
2364  friend half operator+(half, half);
2365  friend half operator-(half, half);
2366  friend half operator*(half, half);
2367  friend half operator/(half, half);
2368  template <typename charT, typename traits>
2369  friend std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>&, half);
2370  template <typename charT, typename traits>
2371  friend std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>&, half&);
2372  friend HALF_CONSTEXPR half fabs(half);
2373  friend half fmod(half, half);
2374  friend half remainder(half, half);
2375  friend half remquo(half, half, int*);
2376  friend half fma(half, half, half);
2379  friend half fdim(half, half);
2380  friend half nanh(const char*);
2381  friend half exp(half);
2382  friend half exp2(half);
2383  friend half expm1(half);
2384  friend half log(half);
2385  friend half log10(half);
2386  friend half log2(half);
2387  friend half log1p(half);
2388  friend half sqrt(half);
2389  friend half rsqrt(half);
2390  friend half cbrt(half);
2391  friend half hypot(half, half);
2392  friend half hypot(half, half, half);
2393  friend half pow(half, half);
2394  friend void sincos(half, half*, half*);
2395  friend half sin(half);
2396  friend half cos(half);
2397  friend half tan(half);
2398  friend half asin(half);
2399  friend half acos(half);
2400  friend half atan(half);
2401  friend half atan2(half, half);
2402  friend half sinh(half);
2403  friend half cosh(half);
2404  friend half tanh(half);
2405  friend half asinh(half);
2406  friend half acosh(half);
2407  friend half atanh(half);
2408  friend half erf(half);
2409  friend half erfc(half);
2410  friend half lgamma(half);
2411  friend half tgamma(half);
2412  friend half ceil(half);
2413  friend half floor(half);
2414  friend half trunc(half);
2415  friend half round(half);
2416  friend long lround(half);
2417  friend half rint(half);
2418  friend long lrint(half);
2419  friend half nearbyint(half);
2420 #ifdef HALF_ENABLE_CPP11_LONG_LONG
2421  friend long long llround(half);
2422  friend long long llrint(half);
2423 #endif
2424  friend half frexp(half, int*);
2425  friend half scalbln(half, long);
2426  friend half modf(half, half*);
2427  friend int ilogb(half);
2428  friend half logb(half);
2429  friend half nextafter(half, half);
2430  friend half nexttoward(half, long double);
2432  friend HALF_CONSTEXPR int fpclassify(half);
2433  friend HALF_CONSTEXPR bool isfinite(half);
2434  friend HALF_CONSTEXPR bool isinf(half);
2435  friend HALF_CONSTEXPR bool isnan(half);
2436  friend HALF_CONSTEXPR bool isnormal(half);
2437  friend HALF_CONSTEXPR bool signbit(half);
2438  friend HALF_CONSTEXPR bool isgreater(half, half);
2439  friend HALF_CONSTEXPR bool isgreaterequal(half, half);
2440  friend HALF_CONSTEXPR bool isless(half, half);
2441  friend HALF_CONSTEXPR bool islessequal(half, half);
2442  friend HALF_CONSTEXPR bool islessgreater(half, half);
2443  template <typename, typename, std::float_round_style> friend struct detail::half_caster;
2444  friend class std::numeric_limits<half>;
2445 #if HALF_ENABLE_CPP11_HASH
2446  friend struct std::hash<half>;
2447 #endif
2448 #if HALF_ENABLE_CPP11_USER_LITERALS
2449  friend half literal::operator"" _h(long double);
2450 #endif
2451 #endif
2452 };
2453 
2454 #if HALF_ENABLE_CPP11_USER_LITERALS
2455 namespace literal {
2463  inline half operator"" _h(long double value)
2464  {
2465  return half(detail::binary, detail::float2half<half::round_style>(value));
2466  }
2467 } // namespace literal
2468 #endif
2469 
2470 namespace detail {
2477  template <typename T, typename U, std::float_round_style R = (std::float_round_style)(HALF_ROUND_STYLE)>
2478  struct half_caster {
2479  };
2480  template <typename U, std::float_round_style R> struct half_caster<half, U, R> {
2481 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
2482  static_assert(std::is_arithmetic<U>::value, "half_cast from non-arithmetic type unsupported");
2483 #endif
2484 
2485  static half cast(U arg) { return cast_impl(arg, is_float<U>()); };
2486 
2487  private:
2488  static half cast_impl(U arg, true_type) { return half(binary, float2half<R>(arg)); }
2489  static half cast_impl(U arg, false_type) { return half(binary, int2half<R>(arg)); }
2490  };
2491  template <typename T, std::float_round_style R> struct half_caster<T, half, R> {
2492 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
2493  static_assert(std::is_arithmetic<T>::value, "half_cast to non-arithmetic type unsupported");
2494 #endif
2495 
2496  static T cast(half arg) { return cast_impl(arg, is_float<T>()); }
2497 
2498  private:
2499  static T cast_impl(half arg, true_type) { return half2float<T>(arg.data_); }
2500  static T cast_impl(half arg, false_type) { return half2int<R, true, true, T>(arg.data_); }
2501  };
2502  template <std::float_round_style R> struct half_caster<half, half, R> {
2503  static half cast(half arg) { return arg; }
2504  };
2505 } // namespace detail
2506 } // namespace half_float
2507 
2509 namespace std {
2512 template <> class numeric_limits<half_float::half> {
2513 public:
2515  static HALF_CONSTEXPR_CONST bool is_specialized = true;
2516 
2518  static HALF_CONSTEXPR_CONST bool is_signed = true;
2519 
2521  static HALF_CONSTEXPR_CONST bool is_integer = false;
2522 
2524  static HALF_CONSTEXPR_CONST bool is_exact = false;
2525 
2527  static HALF_CONSTEXPR_CONST bool is_modulo = false;
2528 
2530  static HALF_CONSTEXPR_CONST bool is_bounded = true;
2531 
2533  static HALF_CONSTEXPR_CONST bool is_iec559 = true;
2534 
2536  static HALF_CONSTEXPR_CONST bool has_infinity = true;
2537 
2539  static HALF_CONSTEXPR_CONST bool has_quiet_NaN = true;
2540 
2542  static HALF_CONSTEXPR_CONST bool has_signaling_NaN = true;
2543 
2545  static HALF_CONSTEXPR_CONST float_denorm_style has_denorm = denorm_present;
2546 
2548  static HALF_CONSTEXPR_CONST bool has_denorm_loss = false;
2549 
2550 #if HALF_ERRHANDLING_THROWS
2551  static HALF_CONSTEXPR_CONST bool traps = true;
2552 #else
2554  static HALF_CONSTEXPR_CONST bool traps = false;
2555 #endif
2556 
2558  static HALF_CONSTEXPR_CONST bool tinyness_before = false;
2559 
2561  static HALF_CONSTEXPR_CONST float_round_style round_style = half_float::half::round_style;
2562 
2564  static HALF_CONSTEXPR_CONST int digits = 11;
2565 
2567  static HALF_CONSTEXPR_CONST int digits10 = 3;
2568 
2570  static HALF_CONSTEXPR_CONST int max_digits10 = 5;
2571 
2573  static HALF_CONSTEXPR_CONST int radix = 2;
2574 
2576  static HALF_CONSTEXPR_CONST int min_exponent = -13;
2577 
2579  static HALF_CONSTEXPR_CONST int min_exponent10 = -4;
2580 
2582  static HALF_CONSTEXPR_CONST int max_exponent = 16;
2583 
2585  static HALF_CONSTEXPR_CONST int max_exponent10 = 4;
2586 
2589  {
2591  }
2592 
2595  {
2597  }
2598 
2601  {
2603  }
2604 
2607  {
2609  }
2610 
2613  {
2614  return half_float::half(half_float::detail::binary, (round_style == std::round_to_nearest) ? 0x3800 : 0x3C00);
2615  }
2616 
2619  {
2621  }
2622 
2625  {
2627  }
2628 
2631  {
2633  }
2634 
2637  {
2639  }
2640 };
2641 
2642 #if HALF_ENABLE_CPP11_HASH
2647 template <> struct hash<half_float::half> {
2649  typedef half_float::half argument_type;
2650 
2652  typedef size_t result_type;
2653 
2657  result_type operator()(argument_type arg) const
2658  {
2659  return hash<half_float::detail::uint16>()(arg.data_ & -static_cast<unsigned>(arg.data_ != 0x8000));
2660  }
2661 };
2662 #endif
2663 } // namespace std
2664 
2665 namespace half_float {
2669 
2677 {
2678  return !detail::compsignal(x.data_, y.data_) && (x.data_ == y.data_ || !((x.data_ | y.data_) & 0x7FFF));
2679 }
2680 
2688 {
2689  return detail::compsignal(x.data_, y.data_) || (x.data_ != y.data_ && ((x.data_ | y.data_) & 0x7FFF));
2690 }
2691 
2699 {
2700  return !detail::compsignal(x.data_, y.data_) &&
2701  ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) <
2702  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15));
2703 }
2704 
2712 {
2713  return !detail::compsignal(x.data_, y.data_) &&
2714  ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) >
2715  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15));
2716 }
2717 
2725 {
2726  return !detail::compsignal(x.data_, y.data_) &&
2727  ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) <=
2728  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15));
2729 }
2730 
2738 {
2739  return !detail::compsignal(x.data_, y.data_) &&
2740  ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) >=
2741  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15));
2742 }
2743 
2748 
2752 inline HALF_CONSTEXPR half operator+(half arg) { return arg; }
2753 
2757 inline HALF_CONSTEXPR half operator-(half arg) { return half(detail::binary, arg.data_ ^ 0x8000); }
2758 
2766 inline half operator+(half x, half y)
2767 {
2768 #ifdef HALF_ARITHMETIC_TYPE
2769  return half(detail::binary,
2770  detail::float2half<half::round_style>(
2771  detail::half2float<detail::internal_t>(x.data_) + detail::half2float<detail::internal_t>(y.data_)));
2772 #else
2773  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF;
2774  bool sub = ((x.data_ ^ y.data_) & 0x8000) != 0;
2775  if (absx >= 0x7C00 || absy >= 0x7C00)
2776  return half(detail::binary,
2777  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
2778  : (absy != 0x7C00) ? x.data_
2779  : (sub && absx == 0x7C00) ? detail::invalid()
2780  : y.data_);
2781  if (!absx)
2782  return absy
2783  ? y
2784  : half(detail::binary,
2785  (half::round_style == std::round_toward_neg_infinity) ? (x.data_ | y.data_) : (x.data_ & y.data_));
2786  if (!absy)
2787  return x;
2788  unsigned int sign = ((sub && absy > absx) ? y.data_ : x.data_) & 0x8000;
2789  if (absy > absx)
2790  std::swap(absx, absy);
2791  int exp = (absx >> 10) + (absx <= 0x3FF), d = exp - (absy >> 10) - (absy <= 0x3FF),
2792  mx = ((absx & 0x3FF) | ((absx > 0x3FF) << 10)) << 3, my;
2793  if (d < 13) {
2794  my = ((absy & 0x3FF) | ((absy > 0x3FF) << 10)) << 3;
2795  my = (my >> d) | ((my & ((1 << d) - 1)) != 0);
2796  } else
2797  my = 1;
2798  if (sub) {
2799  if (!(mx -= my))
2800  return half(
2801  detail::binary, static_cast<unsigned>(half::round_style == std::round_toward_neg_infinity) << 15);
2802  for (; mx < 0x2000 && exp > 1; mx <<= 1, --exp)
2803  ;
2804  } else {
2805  mx += my;
2806  int i = mx >> 14;
2807  if ((exp += i) > 30)
2808  return half(detail::binary, detail::overflow<half::round_style>(sign));
2809  mx = (mx >> i) | (mx & i);
2810  }
2811  return half(detail::binary,
2812  detail::rounded<half::round_style, false>(
2813  sign + ((exp - 1) << 10) + (mx >> 3), (mx >> 2) & 1, (mx & 0x3) != 0));
2814 #endif
2815 }
2816 
2824 inline half operator-(half x, half y)
2825 {
2826 #ifdef HALF_ARITHMETIC_TYPE
2827  return half(detail::binary,
2828  detail::float2half<half::round_style>(
2829  detail::half2float<detail::internal_t>(x.data_) - detail::half2float<detail::internal_t>(y.data_)));
2830 #else
2831  return x + -y;
2832 #endif
2833 }
2834 
2842 inline half operator*(half x, half y)
2843 {
2844 #ifdef HALF_ARITHMETIC_TYPE
2845  return half(detail::binary,
2846  detail::float2half<half::round_style>(
2847  detail::half2float<detail::internal_t>(x.data_) * detail::half2float<detail::internal_t>(y.data_)));
2848 #else
2849  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, exp = -16;
2850  unsigned int sign = (x.data_ ^ y.data_) & 0x8000;
2851  if (absx >= 0x7C00 || absy >= 0x7C00)
2852  return half(detail::binary,
2853  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
2854  : ((absx == 0x7C00 && !absy) || (absy == 0x7C00 && !absx)) ? detail::invalid()
2855  : (sign | 0x7C00));
2856  if (!absx || !absy)
2857  return half(detail::binary, sign);
2858  for (; absx < 0x400; absx <<= 1, --exp)
2859  ;
2860  for (; absy < 0x400; absy <<= 1, --exp)
2861  ;
2862  detail::uint32 m =
2863  static_cast<detail::uint32>((absx & 0x3FF) | 0x400) * static_cast<detail::uint32>((absy & 0x3FF) | 0x400);
2864  int i = m >> 21, s = m & i;
2865  exp += (absx >> 10) + (absy >> 10) + i;
2866  if (exp > 29)
2867  return half(detail::binary, detail::overflow<half::round_style>(sign));
2868  else if (exp < -11)
2869  return half(detail::binary, detail::underflow<half::round_style>(sign));
2870  return half(detail::binary, detail::fixed2half<half::round_style, 20, false, false, false>(m >> i, exp, sign, s));
2871 #endif
2872 }
2873 
2882 inline half operator/(half x, half y)
2883 {
2884 #ifdef HALF_ARITHMETIC_TYPE
2885  return half(detail::binary,
2886  detail::float2half<half::round_style>(
2887  detail::half2float<detail::internal_t>(x.data_) / detail::half2float<detail::internal_t>(y.data_)));
2888 #else
2889  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, exp = 14;
2890  unsigned int sign = (x.data_ ^ y.data_) & 0x8000;
2891  if (absx >= 0x7C00 || absy >= 0x7C00)
2892  return half(detail::binary,
2893  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
2894  : (absx == absy) ? detail::invalid()
2895  : (sign | ((absx == 0x7C00) ? 0x7C00 : 0)));
2896  if (!absx)
2897  return half(detail::binary, absy ? sign : detail::invalid());
2898  if (!absy)
2899  return half(detail::binary, detail::pole(sign));
2900  for (; absx < 0x400; absx <<= 1, --exp)
2901  ;
2902  for (; absy < 0x400; absy <<= 1, ++exp)
2903  ;
2904  detail::uint32 mx = (absx & 0x3FF) | 0x400, my = (absy & 0x3FF) | 0x400;
2905  int i = mx < my;
2906  exp += (absx >> 10) - (absy >> 10) - i;
2907  if (exp > 29)
2908  return half(detail::binary, detail::overflow<half::round_style>(sign));
2909  else if (exp < -11)
2910  return half(detail::binary, detail::underflow<half::round_style>(sign));
2911  mx <<= 12 + i;
2912  my <<= 1;
2913  return half(detail::binary,
2914  detail::fixed2half<half::round_style, 11, false, false, false>(mx / my, exp, sign, mx % my != 0));
2915 #endif
2916 }
2917 
2922 
2928 template <typename charT, typename traits>
2929 std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out, half arg)
2930 {
2931 #ifdef HALF_ARITHMETIC_TYPE
2932  return out << detail::half2float<detail::internal_t>(arg.data_);
2933 #else
2934  return out << detail::half2float<float>(arg.data_);
2935 #endif
2936 }
2937 
2947 template <typename charT, typename traits>
2948 std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& in, half& arg)
2949 {
2950 #ifdef HALF_ARITHMETIC_TYPE
2951  detail::internal_t f;
2952 #else
2953  double f;
2954 #endif
2955  if (in >> f)
2956  arg.data_ = detail::float2half<half::round_style>(f);
2957  return in;
2958 }
2959 
2964 
2969 inline HALF_CONSTEXPR half fabs(half arg) { return half(detail::binary, arg.data_ & 0x7FFF); }
2970 
2975 inline HALF_CONSTEXPR half abs(half arg) { return fabs(arg); }
2976 
2983 inline half fmod(half x, half y)
2984 {
2985  unsigned int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, sign = x.data_ & 0x8000;
2986  if (absx >= 0x7C00 || absy >= 0x7C00)
2987  return half(detail::binary,
2988  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
2989  : (absx == 0x7C00) ? detail::invalid()
2990  : x.data_);
2991  if (!absy)
2992  return half(detail::binary, detail::invalid());
2993  if (!absx)
2994  return x;
2995  if (absx == absy)
2996  return half(detail::binary, sign);
2997  return half(detail::binary, sign | detail::mod<false, false>(absx, absy));
2998 }
2999 
3006 inline half remainder(half x, half y)
3007 {
3008  unsigned int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, sign = x.data_ & 0x8000;
3009  if (absx >= 0x7C00 || absy >= 0x7C00)
3010  return half(detail::binary,
3011  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
3012  : (absx == 0x7C00) ? detail::invalid()
3013  : x.data_);
3014  if (!absy)
3015  return half(detail::binary, detail::invalid());
3016  if (absx == absy)
3017  return half(detail::binary, sign);
3018  return half(detail::binary, sign ^ detail::mod<false, true>(absx, absy));
3019 }
3020 
3028 inline half remquo(half x, half y, int* quo)
3029 {
3030  unsigned int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, value = x.data_ & 0x8000;
3031  if (absx >= 0x7C00 || absy >= 0x7C00)
3032  return half(detail::binary,
3033  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
3034  : (absx == 0x7C00) ? detail::invalid()
3035  : (*quo = 0, x.data_));
3036  if (!absy)
3037  return half(detail::binary, detail::invalid());
3038  bool qsign = ((value ^ y.data_) & 0x8000) != 0;
3039  int q = 1;
3040  if (absx != absy)
3041  value ^= detail::mod<true, true>(absx, absy, &q);
3042  return *quo = qsign ? -q : q, half(detail::binary, value);
3043 }
3044 
3055 inline half fma(half x, half y, half z)
3056 {
3057 #ifdef HALF_ARITHMETIC_TYPE
3058  detail::internal_t fx = detail::half2float<detail::internal_t>(x.data_),
3059  fy = detail::half2float<detail::internal_t>(y.data_),
3060  fz = detail::half2float<detail::internal_t>(z.data_);
3061 #if HALF_ENABLE_CPP11_CMATH && FP_FAST_FMA
3062  return half(detail::binary, detail::float2half<half::round_style>(std::fma(fx, fy, fz)));
3063 #else
3064  return half(detail::binary, detail::float2half<half::round_style>(fx * fy + fz));
3065 #endif
3066 #else
3067  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, absz = z.data_ & 0x7FFF, exp = -15;
3068  unsigned int sign = (x.data_ ^ y.data_) & 0x8000;
3069  bool sub = ((sign ^ z.data_) & 0x8000) != 0;
3070  if (absx >= 0x7C00 || absy >= 0x7C00 || absz >= 0x7C00)
3071  return (absx > 0x7C00 || absy > 0x7C00 || absz > 0x7C00)
3073  : (absx == 0x7C00)
3074  ? half(detail::binary, (!absy || (sub && absz == 0x7C00)) ? detail::invalid() : (sign | 0x7C00))
3075  : (absy == 0x7C00)
3076  ? half(detail::binary, (!absx || (sub && absz == 0x7C00)) ? detail::invalid() : (sign | 0x7C00))
3077  : z;
3078  if (!absx || !absy)
3079  return absz ? z
3080  : half(detail::binary,
3081  (half::round_style == std::round_toward_neg_infinity) ? (z.data_ | sign) : (z.data_ & sign));
3082  for (; absx < 0x400; absx <<= 1, --exp)
3083  ;
3084  for (; absy < 0x400; absy <<= 1, --exp)
3085  ;
3086  detail::uint32 m =
3087  static_cast<detail::uint32>((absx & 0x3FF) | 0x400) * static_cast<detail::uint32>((absy & 0x3FF) | 0x400);
3088  int i = m >> 21;
3089  exp += (absx >> 10) + (absy >> 10) + i;
3090  m <<= 3 - i;
3091  if (absz) {
3092  int expz = 0;
3093  for (; absz < 0x400; absz <<= 1, --expz)
3094  ;
3095  expz += absz >> 10;
3096  detail::uint32 mz = static_cast<detail::uint32>((absz & 0x3FF) | 0x400) << 13;
3097  if (expz > exp || (expz == exp && mz > m)) {
3098  std::swap(m, mz);
3099  std::swap(exp, expz);
3100  if (sub)
3101  sign = z.data_ & 0x8000;
3102  }
3103  int d = exp - expz;
3104  mz = (d < 23) ? ((mz >> d) | ((mz & ((static_cast<detail::uint32>(1) << d) - 1)) != 0)) : 1;
3105  if (sub) {
3106  m = m - mz;
3107  if (!m)
3108  return half(
3109  detail::binary, static_cast<unsigned>(half::round_style == std::round_toward_neg_infinity) << 15);
3110  for (; m < 0x800000; m <<= 1, --exp)
3111  ;
3112  } else {
3113  m += mz;
3114  i = m >> 24;
3115  m = (m >> i) | (m & i);
3116  exp += i;
3117  }
3118  }
3119  if (exp > 30)
3120  return half(detail::binary, detail::overflow<half::round_style>(sign));
3121  else if (exp < -10)
3122  return half(detail::binary, detail::underflow<half::round_style>(sign));
3123  return half(detail::binary, detail::fixed2half<half::round_style, 23, false, false, false>(m, exp - 1, sign));
3124 #endif
3125 }
3126 
3134 {
3135  return half(detail::binary,
3136  (!isnan(y) &&
3137  (isnan(x) ||
3138  (x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) < (y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15))))))
3139  ? detail::select(y.data_, x.data_)
3140  : detail::select(x.data_, y.data_));
3141 }
3142 
3150 {
3151  return half(detail::binary,
3152  (!isnan(y) &&
3153  (isnan(x) ||
3154  (x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) > (y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15))))))
3155  ? detail::select(y.data_, x.data_)
3156  : detail::select(x.data_, y.data_));
3157 }
3158 
3167 inline half fdim(half x, half y)
3168 {
3169  if (isnan(x) || isnan(y))
3170  return half(detail::binary, detail::signal(x.data_, y.data_));
3171  return (x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) <= (y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15))))
3172  ? half(detail::binary, 0)
3173  : (x - y);
3174 }
3175 
3180 inline half nanh(const char* arg)
3181 {
3182  unsigned int value = 0x7FFF;
3183  while (*arg)
3184  value ^= static_cast<unsigned>(*arg++) & 0xFF;
3185  return half(detail::binary, value);
3186 }
3187 
3192 
3201 inline half exp(half arg)
3202 {
3203 #ifdef HALF_ARITHMETIC_TYPE
3204  return half(detail::binary,
3205  detail::float2half<half::round_style>(std::exp(detail::half2float<detail::internal_t>(arg.data_))));
3206 #else
3207  int abs = arg.data_ & 0x7FFF, e = (abs >> 10) + (abs <= 0x3FF), exp;
3208  if (!abs)
3209  return half(detail::binary, 0x3C00);
3210  if (abs >= 0x7C00)
3211  return half(detail::binary, (abs == 0x7C00) ? (0x7C00 & ((arg.data_ >> 15) - 1U)) : detail::signal(arg.data_));
3212  if (abs >= 0x4C80)
3213  return half(detail::binary,
3214  (arg.data_ & 0x8000) ? detail::underflow<half::round_style>() : detail::overflow<half::round_style>());
3215  detail::uint32 m =
3216  detail::multiply64(static_cast<detail::uint32>((abs & 0x3FF) + ((abs > 0x3FF) << 10)) << 21, 0xB8AA3B29);
3217  if (e < 14) {
3218  exp = 0;
3219  m >>= 14 - e;
3220  } else {
3221  exp = m >> (45 - e);
3222  m = (m << (e - 14)) & 0x7FFFFFFF;
3223  }
3224  return half(detail::binary, detail::exp2_post<half::round_style>(m, exp, (arg.data_ & 0x8000) != 0, 0, 26));
3225 #endif
3226 }
3227 
3236 inline half exp2(half arg)
3237 {
3238 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
3239  return half(detail::binary,
3240  detail::float2half<half::round_style>(std::exp2(detail::half2float<detail::internal_t>(arg.data_))));
3241 #else
3242  int abs = arg.data_ & 0x7FFF, e = (abs >> 10) + (abs <= 0x3FF), exp = (abs & 0x3FF) + ((abs > 0x3FF) << 10);
3243  if (!abs)
3244  return half(detail::binary, 0x3C00);
3245  if (abs >= 0x7C00)
3246  return half(detail::binary, (abs == 0x7C00) ? (0x7C00 & ((arg.data_ >> 15) - 1U)) : detail::signal(arg.data_));
3247  if (abs >= 0x4E40)
3248  return half(detail::binary,
3249  (arg.data_ & 0x8000) ? detail::underflow<half::round_style>() : detail::overflow<half::round_style>());
3250  return half(detail::binary,
3251  detail::exp2_post<half::round_style>((static_cast<detail::uint32>(exp) << (6 + e)) & 0x7FFFFFFF,
3252  exp >> (25 - e), (arg.data_ & 0x8000) != 0, 0, 28));
3253 #endif
3254 }
3255 
3265 inline half expm1(half arg)
3266 {
3267 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
3268  return half(detail::binary,
3269  detail::float2half<half::round_style>(std::expm1(detail::half2float<detail::internal_t>(arg.data_))));
3270 #else
3271  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000, e = (abs >> 10) + (abs <= 0x3FF), exp;
3272  if (!abs)
3273  return arg;
3274  if (abs >= 0x7C00)
3275  return half(detail::binary, (abs == 0x7C00) ? (0x7C00 + (sign >> 1)) : detail::signal(arg.data_));
3276  if (abs >= 0x4A00)
3277  return half(detail::binary,
3278  (arg.data_ & 0x8000) ? detail::rounded<half::round_style, true>(0xBBFF, 1, 1)
3279  : detail::overflow<half::round_style>());
3280  detail::uint32 m =
3281  detail::multiply64(static_cast<detail::uint32>((abs & 0x3FF) + ((abs > 0x3FF) << 10)) << 21, 0xB8AA3B29);
3282  if (e < 14) {
3283  exp = 0;
3284  m >>= 14 - e;
3285  } else {
3286  exp = m >> (45 - e);
3287  m = (m << (e - 14)) & 0x7FFFFFFF;
3288  }
3289  m = detail::exp2(m);
3290  if (sign) {
3291  int s = 0;
3292  if (m > 0x80000000) {
3293  ++exp;
3294  m = detail::divide64(0x80000000, m, s);
3295  }
3296  m = 0x80000000 - ((m >> exp) | ((m & ((static_cast<detail::uint32>(1) << exp) - 1)) != 0) | s);
3297  exp = 0;
3298  } else
3299  m -= (exp < 31) ? (0x80000000 >> exp) : 1;
3300  for (exp += 14; m < 0x80000000 && exp; m <<= 1, --exp)
3301  ;
3302  if (exp > 29)
3303  return half(detail::binary, detail::overflow<half::round_style>());
3304  return half(detail::binary,
3305  detail::rounded<half::round_style, true>(sign + (exp << 10) + (m >> 21), (m >> 20) & 1, (m & 0xFFFFF) != 0));
3306 #endif
3307 }
3308 
3318 inline half log(half arg)
3319 {
3320 #ifdef HALF_ARITHMETIC_TYPE
3321  return half(detail::binary,
3322  detail::float2half<half::round_style>(std::log(detail::half2float<detail::internal_t>(arg.data_))));
3323 #else
3324  int abs = arg.data_ & 0x7FFF, exp = -15;
3325  if (!abs)
3326  return half(detail::binary, detail::pole(0x8000));
3327  if (arg.data_ & 0x8000)
3328  return half(detail::binary, (arg.data_ <= 0xFC00) ? detail::invalid() : detail::signal(arg.data_));
3329  if (abs >= 0x7C00)
3330  return (abs == 0x7C00) ? arg : half(detail::binary, detail::signal(arg.data_));
3331  for (; abs < 0x400; abs <<= 1, --exp)
3332  ;
3333  exp += abs >> 10;
3334  return half(detail::binary,
3335  detail::log2_post<half::round_style, 0xB8AA3B2A>(
3336  detail::log2(static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 20, 27) + 8, exp, 17));
3337 #endif
3338 }
3339 
3349 inline half log10(half arg)
3350 {
3351 #ifdef HALF_ARITHMETIC_TYPE
3352  return half(detail::binary,
3353  detail::float2half<half::round_style>(std::log10(detail::half2float<detail::internal_t>(arg.data_))));
3354 #else
3355  int abs = arg.data_ & 0x7FFF, exp = -15;
3356  if (!abs)
3357  return half(detail::binary, detail::pole(0x8000));
3358  if (arg.data_ & 0x8000)
3359  return half(detail::binary, (arg.data_ <= 0xFC00) ? detail::invalid() : detail::signal(arg.data_));
3360  if (abs >= 0x7C00)
3361  return (abs == 0x7C00) ? arg : half(detail::binary, detail::signal(arg.data_));
3362  switch (abs) {
3363  case 0x4900:
3364  return half(detail::binary, 0x3C00);
3365  case 0x5640:
3366  return half(detail::binary, 0x4000);
3367  case 0x63D0:
3368  return half(detail::binary, 0x4200);
3369  case 0x70E2:
3370  return half(detail::binary, 0x4400);
3371  }
3372  for (; abs < 0x400; abs <<= 1, --exp)
3373  ;
3374  exp += abs >> 10;
3375  return half(detail::binary,
3376  detail::log2_post<half::round_style, 0xD49A784C>(
3377  detail::log2(static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 20, 27) + 8, exp, 16));
3378 #endif
3379 }
3380 
3390 inline half log2(half arg)
3391 {
3392 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
3393  return half(detail::binary,
3394  detail::float2half<half::round_style>(std::log2(detail::half2float<detail::internal_t>(arg.data_))));
3395 #else
3396  int abs = arg.data_ & 0x7FFF, exp = -15, s = 0;
3397  if (!abs)
3398  return half(detail::binary, detail::pole(0x8000));
3399  if (arg.data_ & 0x8000)
3400  return half(detail::binary, (arg.data_ <= 0xFC00) ? detail::invalid() : detail::signal(arg.data_));
3401  if (abs >= 0x7C00)
3402  return (abs == 0x7C00) ? arg : half(detail::binary, detail::signal(arg.data_));
3403  if (abs == 0x3C00)
3404  return half(detail::binary, 0);
3405  for (; abs < 0x400; abs <<= 1, --exp)
3406  ;
3407  exp += (abs >> 10);
3408  if (!(abs & 0x3FF)) {
3409  unsigned int value = static_cast<unsigned>(exp < 0) << 15, m = std::abs(exp) << 6;
3410  for (exp = 18; m < 0x400; m <<= 1, --exp)
3411  ;
3412  return half(detail::binary, value + (exp << 10) + m);
3413  }
3414  detail::uint32 ilog = exp, sign = detail::sign_mask(ilog),
3415  m = (((ilog << 27) +
3416  (detail::log2(static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 20, 28) >> 4)) ^
3417  sign) -
3418  sign;
3419  if (!m)
3420  return half(detail::binary, 0);
3421  for (exp = 14; m < 0x8000000 && exp; m <<= 1, --exp)
3422  ;
3423  for (; m > 0xFFFFFFF; m >>= 1, ++exp)
3424  s |= m & 1;
3425  return half(
3426  detail::binary, detail::fixed2half<half::round_style, 27, false, false, true>(m, exp, sign & 0x8000, s));
3427 #endif
3428 }
3429 
3440 inline half log1p(half arg)
3441 {
3442 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
3443  return half(detail::binary,
3444  detail::float2half<half::round_style>(std::log1p(detail::half2float<detail::internal_t>(arg.data_))));
3445 #else
3446  if (arg.data_ >= 0xBC00)
3447  return half(detail::binary,
3448  (arg.data_ == 0xBC00) ? detail::pole(0x8000)
3449  : (arg.data_ <= 0xFC00) ? detail::invalid()
3450  : detail::signal(arg.data_));
3451  int abs = arg.data_ & 0x7FFF, exp = -15;
3452  if (!abs || abs >= 0x7C00)
3453  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
3454  for (; abs < 0x400; abs <<= 1, --exp)
3455  ;
3456  exp += abs >> 10;
3457  detail::uint32 m = static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 20;
3458  if (arg.data_ & 0x8000) {
3459  m = 0x40000000 - (m >> -exp);
3460  for (exp = 0; m < 0x40000000; m <<= 1, --exp)
3461  ;
3462  } else {
3463  if (exp < 0) {
3464  m = 0x40000000 + (m >> -exp);
3465  exp = 0;
3466  } else {
3467  m += 0x40000000 >> exp;
3468  int i = m >> 31;
3469  m >>= i;
3470  exp += i;
3471  }
3472  }
3473  return half(detail::binary, detail::log2_post<half::round_style, 0xB8AA3B2A>(detail::log2(m), exp, 17));
3474 #endif
3475 }
3476 
3481 
3490 inline half sqrt(half arg)
3491 {
3492 #ifdef HALF_ARITHMETIC_TYPE
3493  return half(detail::binary,
3494  detail::float2half<half::round_style>(std::sqrt(detail::half2float<detail::internal_t>(arg.data_))));
3495 #else
3496  int abs = arg.data_ & 0x7FFF, exp = 15;
3497  if (!abs || arg.data_ >= 0x7C00)
3498  return half(detail::binary,
3499  (abs > 0x7C00) ? detail::signal(arg.data_)
3500  : (arg.data_ > 0x8000) ? detail::invalid()
3501  : arg.data_);
3502  for (; abs < 0x400; abs <<= 1, --exp)
3503  ;
3504  detail::uint32 r = static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 10,
3505  m = detail::sqrt<20>(r, exp += abs >> 10);
3506  return half(detail::binary, detail::rounded<half::round_style, false>((exp << 10) + (m & 0x3FF), r > m, r != 0));
3507 #endif
3508 }
3509 
3517 inline half rsqrt(half arg)
3518 {
3519 #ifdef HALF_ARITHMETIC_TYPE
3520  return half(detail::binary,
3521  detail::float2half<half::round_style>(
3522  detail::internal_t(1) / std::sqrt(detail::half2float<detail::internal_t>(arg.data_))));
3523 #else
3524  unsigned int abs = arg.data_ & 0x7FFF, bias = 0x4000;
3525  if (!abs || arg.data_ >= 0x7C00)
3526  return half(detail::binary,
3527  (abs > 0x7C00) ? detail::signal(arg.data_)
3528  : (arg.data_ > 0x8000) ? detail::invalid()
3529  : !abs ? detail::pole(arg.data_ & 0x8000)
3530  : 0);
3531  for (; abs < 0x400; abs <<= 1, bias -= 0x400)
3532  ;
3533  unsigned int frac = (abs += bias) & 0x7FF;
3534  if (frac == 0x400)
3535  return half(detail::binary, 0x7A00 - (abs >> 1));
3536  if ((half::round_style == std::round_to_nearest && (frac == 0x3FE || frac == 0x76C)) ||
3537  (half::round_style != std::round_to_nearest &&
3538  (frac == 0x15A || frac == 0x3FC || frac == 0x401 || frac == 0x402 || frac == 0x67B)))
3539  return pow(arg, half(detail::binary, 0xB800));
3540  detail::uint32 f = 0x17376 - abs, mx = (abs & 0x3FF) | 0x400, my = ((f >> 1) & 0x3FF) | 0x400, mz = my * my;
3541  int expy = (f >> 11) - 31, expx = 32 - (abs >> 10), i = mz >> 21;
3542  for (mz = 0x60000000 - (((mz >> i) * mx) >> (expx - 2 * expy - i)); mz < 0x40000000; mz <<= 1, --expy)
3543  ;
3544  i = (my *= mz >> 10) >> 31;
3545  expy += i;
3546  my = (my >> (20 + i)) + 1;
3547  i = (mz = my * my) >> 21;
3548  for (mz = 0x60000000 - (((mz >> i) * mx) >> (expx - 2 * expy - i)); mz < 0x40000000; mz <<= 1, --expy)
3549  ;
3550  i = (my *= (mz >> 10) + 1) >> 31;
3551  return half(detail::binary, detail::fixed2half<half::round_style, 30, false, false, true>(my >> i, expy + i + 14));
3552 #endif
3553 }
3554 
3563 inline half cbrt(half arg)
3564 {
3565 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
3566  return half(detail::binary,
3567  detail::float2half<half::round_style>(std::cbrt(detail::half2float<detail::internal_t>(arg.data_))));
3568 #else
3569  int abs = arg.data_ & 0x7FFF, exp = -15;
3570  if (!abs || abs == 0x3C00 || abs >= 0x7C00)
3571  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
3572  for (; abs < 0x400; abs <<= 1, --exp)
3573  ;
3574  detail::uint32 ilog = exp + (abs >> 10), sign = detail::sign_mask(ilog), f,
3575  m = (((ilog << 27) +
3576  (detail::log2(static_cast<detail::uint32>((abs & 0x3FF) | 0x400) << 20, 24) >> 4)) ^
3577  sign) -
3578  sign;
3579  for (exp = 2; m < 0x80000000; m <<= 1, --exp)
3580  ;
3581  m = detail::multiply64(m, 0xAAAAAAAB);
3582  int i = m >> 31, s;
3583  exp += i;
3584  m <<= 1 - i;
3585  if (exp < 0) {
3586  f = m >> -exp;
3587  exp = 0;
3588  } else {
3589  f = (m << exp) & 0x7FFFFFFF;
3590  exp = m >> (31 - exp);
3591  }
3592  m = detail::exp2(f, (half::round_style == std::round_to_nearest) ? 29 : 26);
3593  if (sign) {
3594  if (m > 0x80000000) {
3595  m = detail::divide64(0x80000000, m, s);
3596  ++exp;
3597  }
3598  exp = -exp;
3599  }
3600  return half(detail::binary,
3601  (half::round_style == std::round_to_nearest)
3602  ? detail::fixed2half<half::round_style, 31, false, false, false>(m, exp + 14, arg.data_ & 0x8000)
3603  : detail::fixed2half<half::round_style, 23, false, false, false>(
3604  (m + 0x80) >> 8, exp + 14, arg.data_ & 0x8000));
3605 #endif
3606 }
3607 
3617 inline half hypot(half x, half y)
3618 {
3619 #ifdef HALF_ARITHMETIC_TYPE
3620  detail::internal_t fx = detail::half2float<detail::internal_t>(x.data_),
3621  fy = detail::half2float<detail::internal_t>(y.data_);
3622 #if HALF_ENABLE_CPP11_CMATH
3623  return half(detail::binary, detail::float2half<half::round_style>(std::hypot(fx, fy)));
3624 #else
3625  return half(detail::binary, detail::float2half<half::round_style>(std::sqrt(fx * fx + fy * fy)));
3626 #endif
3627 #else
3628  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, expx = 0, expy = 0;
3629  if (absx >= 0x7C00 || absy >= 0x7C00)
3630  return half(detail::binary,
3631  (absx == 0x7C00) ? detail::select(0x7C00, y.data_)
3632  : (absy == 0x7C00) ? detail::select(0x7C00, x.data_)
3633  : detail::signal(x.data_, y.data_));
3634  if (!absx)
3635  return half(detail::binary, absy ? detail::check_underflow(absy) : 0);
3636  if (!absy)
3638  if (absy > absx)
3639  std::swap(absx, absy);
3640  for (; absx < 0x400; absx <<= 1, --expx)
3641  ;
3642  for (; absy < 0x400; absy <<= 1, --expy)
3643  ;
3644  detail::uint32 mx = (absx & 0x3FF) | 0x400, my = (absy & 0x3FF) | 0x400;
3645  mx *= mx;
3646  my *= my;
3647  int ix = mx >> 21, iy = my >> 21;
3648  expx = 2 * (expx + (absx >> 10)) - 15 + ix;
3649  expy = 2 * (expy + (absy >> 10)) - 15 + iy;
3650  mx <<= 10 - ix;
3651  my <<= 10 - iy;
3652  int d = expx - expy;
3653  my = (d < 30) ? ((my >> d) | ((my & ((static_cast<detail::uint32>(1) << d) - 1)) != 0)) : 1;
3654  return half(detail::binary, detail::hypot_post<half::round_style>(mx + my, expx));
3655 #endif
3656 }
3657 
3668 inline half hypot(half x, half y, half z)
3669 {
3670 #ifdef HALF_ARITHMETIC_TYPE
3671  detail::internal_t fx = detail::half2float<detail::internal_t>(x.data_),
3672  fy = detail::half2float<detail::internal_t>(y.data_),
3673  fz = detail::half2float<detail::internal_t>(z.data_);
3674  return half(detail::binary, detail::float2half<half::round_style>(std::sqrt(fx * fx + fy * fy + fz * fz)));
3675 #else
3676  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, absz = z.data_ & 0x7FFF, expx = 0, expy = 0, expz = 0;
3677  if (!absx)
3678  return hypot(y, z);
3679  if (!absy)
3680  return hypot(x, z);
3681  if (!absz)
3682  return hypot(x, y);
3683  if (absx >= 0x7C00 || absy >= 0x7C00 || absz >= 0x7C00)
3684  return half(detail::binary,
3685  (absx == 0x7C00) ? detail::select(0x7C00, detail::select(y.data_, z.data_))
3686  : (absy == 0x7C00) ? detail::select(0x7C00, detail::select(x.data_, z.data_))
3687  : (absz == 0x7C00) ? detail::select(0x7C00, detail::select(x.data_, y.data_))
3688  : detail::signal(x.data_, y.data_, z.data_));
3689  if (absz > absy)
3690  std::swap(absy, absz);
3691  if (absy > absx)
3692  std::swap(absx, absy);
3693  if (absz > absy)
3694  std::swap(absy, absz);
3695  for (; absx < 0x400; absx <<= 1, --expx)
3696  ;
3697  for (; absy < 0x400; absy <<= 1, --expy)
3698  ;
3699  for (; absz < 0x400; absz <<= 1, --expz)
3700  ;
3701  detail::uint32 mx = (absx & 0x3FF) | 0x400, my = (absy & 0x3FF) | 0x400, mz = (absz & 0x3FF) | 0x400;
3702  mx *= mx;
3703  my *= my;
3704  mz *= mz;
3705  int ix = mx >> 21, iy = my >> 21, iz = mz >> 21;
3706  expx = 2 * (expx + (absx >> 10)) - 15 + ix;
3707  expy = 2 * (expy + (absy >> 10)) - 15 + iy;
3708  expz = 2 * (expz + (absz >> 10)) - 15 + iz;
3709  mx <<= 10 - ix;
3710  my <<= 10 - iy;
3711  mz <<= 10 - iz;
3712  int d = expy - expz;
3713  mz = (d < 30) ? ((mz >> d) | ((mz & ((static_cast<detail::uint32>(1) << d) - 1)) != 0)) : 1;
3714  my += mz;
3715  if (my & 0x80000000) {
3716  my = (my >> 1) | (my & 1);
3717  if (++expy > expx) {
3718  std::swap(mx, my);
3719  std::swap(expx, expy);
3720  }
3721  }
3722  d = expx - expy;
3723  my = (d < 30) ? ((my >> d) | ((my & ((static_cast<detail::uint32>(1) << d) - 1)) != 0)) : 1;
3724  return half(detail::binary, detail::hypot_post<half::round_style>(mx + my, expx));
3725 #endif
3726 }
3727 
3738 inline half pow(half x, half y)
3739 {
3740 #ifdef HALF_ARITHMETIC_TYPE
3741  return half(detail::binary,
3742  detail::float2half<half::round_style>(std::pow(
3743  detail::half2float<detail::internal_t>(x.data_), detail::half2float<detail::internal_t>(y.data_))));
3744 #else
3745  int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, exp = -15;
3746  if (!absy || x.data_ == 0x3C00)
3747  return half(detail::binary, detail::select(0x3C00, (x.data_ == 0x3C00) ? y.data_ : x.data_));
3748  bool is_int = absy >= 0x6400 || (absy >= 0x3C00 && !(absy & ((1 << (25 - (absy >> 10))) - 1)));
3749  unsigned int sign =
3750  x.data_ & (static_cast<unsigned>((absy < 0x6800) && is_int && ((absy >> (25 - (absy >> 10))) & 1)) << 15);
3751  if (absx >= 0x7C00 || absy >= 0x7C00)
3752  return half(detail::binary,
3753  (absx > 0x7C00 || absy > 0x7C00) ? detail::signal(x.data_, y.data_)
3754  : (absy == 0x7C00)
3755  ? ((absx == 0x3C00) ? 0x3C00
3756  : (!absx && y.data_ == 0xFC00) ? detail::pole()
3757  : (0x7C00 & -((y.data_ >> 15) ^ (absx > 0x3C00))))
3758  : (sign | (0x7C00 & ((y.data_ >> 15) - 1U))));
3759  if (!absx)
3760  return half(detail::binary, (y.data_ & 0x8000) ? detail::pole(sign) : sign);
3761  if ((x.data_ & 0x8000) && !is_int)
3762  return half(detail::binary, detail::invalid());
3763  if (x.data_ == 0xBC00)
3764  return half(detail::binary, sign | 0x3C00);
3765  switch (y.data_) {
3766  case 0x3800:
3767  return sqrt(x);
3768  case 0x3C00:
3770  case 0x4000:
3771  return x * x;
3772  case 0xBC00:
3773  return half(detail::binary, 0x3C00) / x;
3774  }
3775  for (; absx < 0x400; absx <<= 1, --exp)
3776  ;
3777  detail::uint32 ilog = exp + (absx >> 10), msign = detail::sign_mask(ilog), f,
3778  m = (((ilog << 27) +
3779  ((detail::log2(static_cast<detail::uint32>((absx & 0x3FF) | 0x400) << 20) + 8) >> 4)) ^
3780  msign) -
3781  msign;
3782  for (exp = -11; m < 0x80000000; m <<= 1, --exp)
3783  ;
3784  for (; absy < 0x400; absy <<= 1, --exp)
3785  ;
3786  m = detail::multiply64(m, static_cast<detail::uint32>((absy & 0x3FF) | 0x400) << 21);
3787  int i = m >> 31;
3788  exp += (absy >> 10) + i;
3789  m <<= 1 - i;
3790  if (exp < 0) {
3791  f = m >> -exp;
3792  exp = 0;
3793  } else {
3794  f = (m << exp) & 0x7FFFFFFF;
3795  exp = m >> (31 - exp);
3796  }
3797  return half(
3798  detail::binary, detail::exp2_post<half::round_style>(f, exp, ((msign & 1) ^ (y.data_ >> 15)) != 0, sign));
3799 #endif
3800 }
3801 
3806 
3816 inline void sincos(half arg, half* sin, half* cos)
3817 {
3818 #ifdef HALF_ARITHMETIC_TYPE
3819  detail::internal_t f = detail::half2float<detail::internal_t>(arg.data_);
3820  *sin = half(detail::binary, detail::float2half<half::round_style>(std::sin(f)));
3821  *cos = half(detail::binary, detail::float2half<half::round_style>(std::cos(f)));
3822 #else
3823  int abs = arg.data_ & 0x7FFF, sign = arg.data_ >> 15, k;
3824  if (abs >= 0x7C00)
3825  *sin = *cos = half(detail::binary, (abs == 0x7C00) ? detail::invalid() : detail::signal(arg.data_));
3826  else if (!abs) {
3827  *sin = arg;
3828  *cos = half(detail::binary, 0x3C00);
3829  } else if (abs < 0x2500) {
3830  *sin = half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 1, 1, 1));
3831  *cos = half(detail::binary, detail::rounded<half::round_style, true>(0x3BFF, 1, 1));
3832  } else {
3833  if (half::round_style != std::round_to_nearest) {
3834  switch (abs) {
3835  case 0x48B7:
3836  *sin = half(
3837  detail::binary, detail::rounded<half::round_style, true>((~arg.data_ & 0x8000) | 0x1D07, 1, 1));
3838  *cos = half(detail::binary, detail::rounded<half::round_style, true>(0xBBFF, 1, 1));
3839  return;
3840  case 0x598C:
3841  *sin =
3842  half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x3BFF, 1, 1));
3843  *cos = half(detail::binary, detail::rounded<half::round_style, true>(0x80FC, 1, 1));
3844  return;
3845  case 0x6A64:
3846  *sin = half(
3847  detail::binary, detail::rounded<half::round_style, true>((~arg.data_ & 0x8000) | 0x3BFE, 1, 1));
3848  *cos = half(detail::binary, detail::rounded<half::round_style, true>(0x27FF, 1, 1));
3849  return;
3850  case 0x6D8C:
3851  *sin =
3852  half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x0FE6, 1, 1));
3853  *cos = half(detail::binary, detail::rounded<half::round_style, true>(0x3BFF, 1, 1));
3854  return;
3855  }
3856  }
3857  std::pair<detail::uint32, detail::uint32> sc = detail::sincos(detail::angle_arg(abs, k), 28);
3858  switch (k & 3) {
3859  case 1:
3860  sc = std::make_pair(sc.second, -sc.first);
3861  break;
3862  case 2:
3863  sc = std::make_pair(-sc.first, -sc.second);
3864  break;
3865  case 3:
3866  sc = std::make_pair(-sc.second, sc.first);
3867  break;
3868  }
3869  *sin = half(detail::binary,
3870  detail::fixed2half<half::round_style, 30, true, true, true>(
3871  (sc.first ^ -static_cast<detail::uint32>(sign)) + sign));
3872  *cos = half(detail::binary, detail::fixed2half<half::round_style, 30, true, true, true>(sc.second));
3873  }
3874 #endif
3875 }
3876 
3885 inline half sin(half arg)
3886 {
3887 #ifdef HALF_ARITHMETIC_TYPE
3888  return half(detail::binary,
3889  detail::float2half<half::round_style>(std::sin(detail::half2float<detail::internal_t>(arg.data_))));
3890 #else
3891  int abs = arg.data_ & 0x7FFF, k;
3892  if (!abs)
3893  return arg;
3894  if (abs >= 0x7C00)
3895  return half(detail::binary, (abs == 0x7C00) ? detail::invalid() : detail::signal(arg.data_));
3896  if (abs < 0x2900)
3897  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 1, 1, 1));
3898  if (half::round_style != std::round_to_nearest)
3899  switch (abs) {
3900  case 0x48B7:
3901  return half(detail::binary, detail::rounded<half::round_style, true>((~arg.data_ & 0x8000) | 0x1D07, 1, 1));
3902  case 0x6A64:
3903  return half(detail::binary, detail::rounded<half::round_style, true>((~arg.data_ & 0x8000) | 0x3BFE, 1, 1));
3904  case 0x6D8C:
3905  return half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x0FE6, 1, 1));
3906  }
3907  std::pair<detail::uint32, detail::uint32> sc = detail::sincos(detail::angle_arg(abs, k), 28);
3908  detail::uint32 sign = -static_cast<detail::uint32>(((k >> 1) & 1) ^ (arg.data_ >> 15));
3909  return half(detail::binary,
3910  detail::fixed2half<half::round_style, 30, true, true, true>((((k & 1) ? sc.second : sc.first) ^ sign) - sign));
3911 #endif
3912 }
3913 
3922 inline half cos(half arg)
3923 {
3924 #ifdef HALF_ARITHMETIC_TYPE
3925  return half(detail::binary,
3926  detail::float2half<half::round_style>(std::cos(detail::half2float<detail::internal_t>(arg.data_))));
3927 #else
3928  int abs = arg.data_ & 0x7FFF, k;
3929  if (!abs)
3930  return half(detail::binary, 0x3C00);
3931  if (abs >= 0x7C00)
3932  return half(detail::binary, (abs == 0x7C00) ? detail::invalid() : detail::signal(arg.data_));
3933  if (abs < 0x2500)
3934  return half(detail::binary, detail::rounded<half::round_style, true>(0x3BFF, 1, 1));
3935  if (half::round_style != std::round_to_nearest && abs == 0x598C)
3936  return half(detail::binary, detail::rounded<half::round_style, true>(0x80FC, 1, 1));
3937  std::pair<detail::uint32, detail::uint32> sc = detail::sincos(detail::angle_arg(abs, k), 28);
3938  detail::uint32 sign = -static_cast<detail::uint32>(((k >> 1) ^ k) & 1);
3939  return half(detail::binary,
3940  detail::fixed2half<half::round_style, 30, true, true, true>((((k & 1) ? sc.first : sc.second) ^ sign) - sign));
3941 #endif
3942 }
3943 
3952 inline half tan(half arg)
3953 {
3954 #ifdef HALF_ARITHMETIC_TYPE
3955  return half(detail::binary,
3956  detail::float2half<half::round_style>(std::tan(detail::half2float<detail::internal_t>(arg.data_))));
3957 #else
3958  int abs = arg.data_ & 0x7FFF, exp = 13, k;
3959  if (!abs)
3960  return arg;
3961  if (abs >= 0x7C00)
3962  return half(detail::binary, (abs == 0x7C00) ? detail::invalid() : detail::signal(arg.data_));
3963  if (abs < 0x2700)
3964  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_, 0, 1));
3965  if (half::round_style != std::round_to_nearest)
3966  switch (abs) {
3967  case 0x658C:
3968  return half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x07E6, 1, 1));
3969  case 0x7330:
3970  return half(detail::binary, detail::rounded<half::round_style, true>((~arg.data_ & 0x8000) | 0x4B62, 1, 1));
3971  }
3972  std::pair<detail::uint32, detail::uint32> sc = detail::sincos(detail::angle_arg(abs, k), 30);
3973  if (k & 1)
3974  sc = std::make_pair(-sc.second, sc.first);
3975  detail::uint32 signy = detail::sign_mask(sc.first), signx = detail::sign_mask(sc.second);
3976  detail::uint32 my = (sc.first ^ signy) - signy, mx = (sc.second ^ signx) - signx;
3977  for (; my < 0x80000000; my <<= 1, --exp)
3978  ;
3979  for (; mx < 0x80000000; mx <<= 1, ++exp)
3980  ;
3981  return half(
3982  detail::binary, detail::tangent_post<half::round_style>(my, mx, exp, (signy ^ signx ^ arg.data_) & 0x8000));
3983 #endif
3984 }
3985 
3994 inline half asin(half arg)
3995 {
3996 #ifdef HALF_ARITHMETIC_TYPE
3997  return half(detail::binary,
3998  detail::float2half<half::round_style>(std::asin(detail::half2float<detail::internal_t>(arg.data_))));
3999 #else
4000  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
4001  if (!abs)
4002  return arg;
4003  if (abs >= 0x3C00)
4004  return half(detail::binary,
4005  (abs > 0x7C00) ? detail::signal(arg.data_)
4006  : (abs > 0x3C00) ? detail::invalid()
4007  : detail::rounded<half::round_style, true>(sign | 0x3E48, 0, 1));
4008  if (abs < 0x2900)
4009  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_, 0, 1));
4010  if (half::round_style != std::round_to_nearest && (abs == 0x2B44 || abs == 0x2DC3))
4011  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ + 1, 1, 1));
4012  std::pair<detail::uint32, detail::uint32> sc = detail::atan2_args(abs);
4013  detail::uint32 m = detail::atan2(sc.first, sc.second, (half::round_style == std::round_to_nearest) ? 27 : 26);
4014  return half(detail::binary, detail::fixed2half<half::round_style, 30, false, true, true>(m, 14, sign));
4015 #endif
4016 }
4017 
4026 inline half acos(half arg)
4027 {
4028 #ifdef HALF_ARITHMETIC_TYPE
4029  return half(detail::binary,
4030  detail::float2half<half::round_style>(std::acos(detail::half2float<detail::internal_t>(arg.data_))));
4031 #else
4032  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ >> 15;
4033  if (!abs)
4034  return half(detail::binary, detail::rounded<half::round_style, true>(0x3E48, 0, 1));
4035  if (abs >= 0x3C00)
4036  return half(detail::binary,
4037  (abs > 0x7C00) ? detail::signal(arg.data_)
4038  : (abs > 0x3C00) ? detail::invalid()
4039  : sign ? detail::rounded<half::round_style, true>(0x4248, 0, 1)
4040  : 0);
4041  std::pair<detail::uint32, detail::uint32> cs = detail::atan2_args(abs);
4042  detail::uint32 m = detail::atan2(cs.second, cs.first, 28);
4043  return half(detail::binary,
4044  detail::fixed2half<half::round_style, 31, false, true, true>(sign ? (0xC90FDAA2 - m) : m, 15, 0, sign));
4045 #endif
4046 }
4047 
4056 inline half atan(half arg)
4057 {
4058 #ifdef HALF_ARITHMETIC_TYPE
4059  return half(detail::binary,
4060  detail::float2half<half::round_style>(std::atan(detail::half2float<detail::internal_t>(arg.data_))));
4061 #else
4062  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
4063  if (!abs)
4064  return arg;
4065  if (abs >= 0x7C00)
4066  return half(detail::binary,
4067  (abs == 0x7C00) ? detail::rounded<half::round_style, true>(sign | 0x3E48, 0, 1)
4068  : detail::signal(arg.data_));
4069  if (abs <= 0x2700)
4070  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 1, 1, 1));
4071  int exp = (abs >> 10) + (abs <= 0x3FF);
4072  detail::uint32 my = (abs & 0x3FF) | ((abs > 0x3FF) << 10);
4073  detail::uint32 m = (exp > 15)
4074  ? detail::atan2(my << 19, 0x20000000 >> (exp - 15), (half::round_style == std::round_to_nearest) ? 26 : 24)
4075  : detail::atan2(my << (exp + 4), 0x20000000, (half::round_style == std::round_to_nearest) ? 30 : 28);
4076  return half(detail::binary, detail::fixed2half<half::round_style, 30, false, true, true>(m, 14, sign));
4077 #endif
4078 }
4079 
4090 inline half atan2(half y, half x)
4091 {
4092 #ifdef HALF_ARITHMETIC_TYPE
4093  return half(detail::binary,
4094  detail::float2half<half::round_style>(std::atan2(
4095  detail::half2float<detail::internal_t>(y.data_), detail::half2float<detail::internal_t>(x.data_))));
4096 #else
4097  unsigned int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, signx = x.data_ >> 15, signy = y.data_ & 0x8000;
4098  if (absx >= 0x7C00 || absy >= 0x7C00) {
4099  if (absx > 0x7C00 || absy > 0x7C00)
4100  return half(detail::binary, detail::signal(x.data_, y.data_));
4101  if (absy == 0x7C00)
4102  return half(detail::binary,
4103  (absx < 0x7C00) ? detail::rounded<half::round_style, true>(signy | 0x3E48, 0, 1)
4104  : signx ? detail::rounded<half::round_style, true>(signy | 0x40B6, 0, 1)
4105  : detail::rounded<half::round_style, true>(signy | 0x3A48, 0, 1));
4106  return (x.data_ == 0x7C00)
4107  ? half(detail::binary, signy)
4108  : half(detail::binary, detail::rounded<half::round_style, true>(signy | 0x4248, 0, 1));
4109  }
4110  if (!absy)
4111  return signx ? half(detail::binary, detail::rounded<half::round_style, true>(signy | 0x4248, 0, 1)) : y;
4112  if (!absx)
4113  return half(detail::binary, detail::rounded<half::round_style, true>(signy | 0x3E48, 0, 1));
4114  int d = (absy >> 10) + (absy <= 0x3FF) - (absx >> 10) - (absx <= 0x3FF);
4115  if (d > (signx ? 18 : 12))
4116  return half(detail::binary, detail::rounded<half::round_style, true>(signy | 0x3E48, 0, 1));
4117  if (signx && d < -11)
4118  return half(detail::binary, detail::rounded<half::round_style, true>(signy | 0x4248, 0, 1));
4119  if (!signx && d < ((half::round_style == std::round_toward_zero) ? -15 : -9)) {
4120  for (; absy < 0x400; absy <<= 1, --d)
4121  ;
4122  detail::uint32 mx = ((absx << 1) & 0x7FF) | 0x800, my = ((absy << 1) & 0x7FF) | 0x800;
4123  int i = my < mx;
4124  d -= i;
4125  if (d < -25)
4126  return half(detail::binary, detail::underflow<half::round_style>(signy));
4127  my <<= 11 + i;
4128  return half(detail::binary,
4129  detail::fixed2half<half::round_style, 11, false, false, true>(my / mx, d + 14, signy, my % mx != 0));
4130  }
4131  detail::uint32 m = detail::atan2(((absy & 0x3FF) | ((absy > 0x3FF) << 10)) << (19 +
4132  ((d < 0) ? d
4133  : (d > 0) ? 0
4134  : -1)),
4135  ((absx & 0x3FF) | ((absx > 0x3FF) << 10)) << (19 -
4136  ((d > 0) ? d
4137  : (d < 0) ? 0
4138  : 1)));
4139  return half(detail::binary,
4140  detail::fixed2half<half::round_style, 31, false, true, true>(signx ? (0xC90FDAA2 - m) : m, 15, signy, signx));
4141 #endif
4142 }
4143 
4148 
4157 inline half sinh(half arg)
4158 {
4159 #ifdef HALF_ARITHMETIC_TYPE
4160  return half(detail::binary,
4161  detail::float2half<half::round_style>(std::sinh(detail::half2float<detail::internal_t>(arg.data_))));
4162 #else
4163  int abs = arg.data_ & 0x7FFF, exp;
4164  if (!abs || abs >= 0x7C00)
4165  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
4166  if (abs <= 0x2900)
4167  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_, 0, 1));
4168  std::pair<detail::uint32, detail::uint32> mm =
4169  detail::hyperbolic_args(abs, exp, (half::round_style == std::round_to_nearest) ? 29 : 27);
4170  detail::uint32 m = mm.first - mm.second;
4171  for (exp += 13; m < 0x80000000 && exp; m <<= 1, --exp)
4172  ;
4173  unsigned int sign = arg.data_ & 0x8000;
4174  if (exp > 29)
4175  return half(detail::binary, detail::overflow<half::round_style>(sign));
4176  return half(detail::binary, detail::fixed2half<half::round_style, 31, false, false, true>(m, exp, sign));
4177 #endif
4178 }
4179 
4188 inline half cosh(half arg)
4189 {
4190 #ifdef HALF_ARITHMETIC_TYPE
4191  return half(detail::binary,
4192  detail::float2half<half::round_style>(std::cosh(detail::half2float<detail::internal_t>(arg.data_))));
4193 #else
4194  int abs = arg.data_ & 0x7FFF, exp;
4195  if (!abs)
4196  return half(detail::binary, 0x3C00);
4197  if (abs >= 0x7C00)
4198  return half(detail::binary, (abs > 0x7C00) ? detail::signal(arg.data_) : 0x7C00);
4199  std::pair<detail::uint32, detail::uint32> mm =
4200  detail::hyperbolic_args(abs, exp, (half::round_style == std::round_to_nearest) ? 23 : 26);
4201  detail::uint32 m = mm.first + mm.second, i = (~m & 0xFFFFFFFF) >> 31;
4202  m = (m >> i) | (m & i) | 0x80000000;
4203  if ((exp += 13 + i) > 29)
4204  return half(detail::binary, detail::overflow<half::round_style>());
4205  return half(detail::binary, detail::fixed2half<half::round_style, 31, false, false, true>(m, exp));
4206 #endif
4207 }
4208 
4217 inline half tanh(half arg)
4218 {
4219 #ifdef HALF_ARITHMETIC_TYPE
4220  return half(detail::binary,
4221  detail::float2half<half::round_style>(std::tanh(detail::half2float<detail::internal_t>(arg.data_))));
4222 #else
4223  int abs = arg.data_ & 0x7FFF, exp;
4224  if (!abs)
4225  return arg;
4226  if (abs >= 0x7C00)
4227  return half(detail::binary, (abs > 0x7C00) ? detail::signal(arg.data_) : (arg.data_ - 0x4000));
4228  if (abs >= 0x4500)
4229  return half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x3BFF, 1, 1));
4230  if (abs < 0x2700)
4231  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 1, 1, 1));
4232  if (half::round_style != std::round_to_nearest && abs == 0x2D3F)
4233  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 3, 0, 1));
4234  std::pair<detail::uint32, detail::uint32> mm = detail::hyperbolic_args(abs, exp, 27);
4235  detail::uint32 my = mm.first - mm.second - (half::round_style != std::round_to_nearest), mx = mm.first + mm.second,
4236  i = (~mx & 0xFFFFFFFF) >> 31;
4237  for (exp = 13; my < 0x80000000; my <<= 1, --exp)
4238  ;
4239  mx = (mx >> i) | 0x80000000;
4240  return half(detail::binary, detail::tangent_post<half::round_style>(my, mx, exp - i, arg.data_ & 0x8000));
4241 #endif
4242 }
4243 
4252 inline half asinh(half arg)
4253 {
4254 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4255  return half(detail::binary,
4256  detail::float2half<half::round_style>(std::asinh(detail::half2float<detail::internal_t>(arg.data_))));
4257 #else
4258  int abs = arg.data_ & 0x7FFF;
4259  if (!abs || abs >= 0x7C00)
4260  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
4261  if (abs <= 0x2900)
4262  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 1, 1, 1));
4263  if (half::round_style != std::round_to_nearest)
4264  switch (abs) {
4265  case 0x32D4:
4266  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 13, 1, 1));
4267  case 0x3B5B:
4268  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_ - 197, 1, 1));
4269  }
4270  return half(detail::binary, detail::area<half::round_style, true>(arg.data_));
4271 #endif
4272 }
4273 
4282 inline half acosh(half arg)
4283 {
4284 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4285  return half(detail::binary,
4286  detail::float2half<half::round_style>(std::acosh(detail::half2float<detail::internal_t>(arg.data_))));
4287 #else
4288  int abs = arg.data_ & 0x7FFF;
4289  if ((arg.data_ & 0x8000) || abs < 0x3C00)
4290  return half(detail::binary, (abs <= 0x7C00) ? detail::invalid() : detail::signal(arg.data_));
4291  if (abs == 0x3C00)
4292  return half(detail::binary, 0);
4293  if (arg.data_ >= 0x7C00)
4294  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
4295  return half(detail::binary, detail::area<half::round_style, false>(arg.data_));
4296 #endif
4297 }
4298 
4308 inline half atanh(half arg)
4309 {
4310 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4311  return half(detail::binary,
4312  detail::float2half<half::round_style>(std::atanh(detail::half2float<detail::internal_t>(arg.data_))));
4313 #else
4314  int abs = arg.data_ & 0x7FFF, exp = 0;
4315  if (!abs)
4316  return arg;
4317  if (abs >= 0x3C00)
4318  return half(detail::binary,
4319  (abs == 0x3C00) ? detail::pole(arg.data_ & 0x8000)
4320  : (abs <= 0x7C00) ? detail::invalid()
4321  : detail::signal(arg.data_));
4322  if (abs < 0x2700)
4323  return half(detail::binary, detail::rounded<half::round_style, true>(arg.data_, 0, 1));
4324  detail::uint32 m = static_cast<detail::uint32>((abs & 0x3FF) | ((abs > 0x3FF) << 10))
4325  << ((abs >> 10) + (abs <= 0x3FF) + 6),
4326  my = 0x80000000 + m, mx = 0x80000000 - m;
4327  for (; mx < 0x80000000; mx <<= 1, ++exp)
4328  ;
4329  int i = my >= mx, s;
4330  return half(detail::binary,
4331  detail::log2_post<half::round_style, 0xB8AA3B2A>(
4332  detail::log2((detail::divide64(my >> i, mx, s) + 1) >> 1, 27) + 0x10, exp + i - 1, 16, arg.data_ & 0x8000));
4333 #endif
4334 }
4335 
4340 
4349 inline half erf(half arg)
4350 {
4351 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4352  return half(detail::binary,
4353  detail::float2half<half::round_style>(std::erf(detail::half2float<detail::internal_t>(arg.data_))));
4354 #else
4355  unsigned int abs = arg.data_ & 0x7FFF;
4356  if (!abs || abs >= 0x7C00)
4357  return (abs >= 0x7C00)
4358  ? half(detail::binary, (abs == 0x7C00) ? (arg.data_ - 0x4000) : detail::signal(arg.data_))
4359  : arg;
4360  if (abs >= 0x4200)
4361  return half(detail::binary, detail::rounded<half::round_style, true>((arg.data_ & 0x8000) | 0x3BFF, 1, 1));
4362  return half(detail::binary, detail::erf<half::round_style, false>(arg.data_));
4363 #endif
4364 }
4365 
4374 inline half erfc(half arg)
4375 {
4376 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4377  return half(detail::binary,
4378  detail::float2half<half::round_style>(std::erfc(detail::half2float<detail::internal_t>(arg.data_))));
4379 #else
4380  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
4381  if (abs >= 0x7C00)
4382  return (abs >= 0x7C00) ? half(detail::binary, (abs == 0x7C00) ? (sign >> 1) : detail::signal(arg.data_)) : arg;
4383  if (!abs)
4384  return half(detail::binary, 0x3C00);
4385  if (abs >= 0x4400)
4386  return half(
4387  detail::binary, detail::rounded<half::round_style, true>((sign >> 1) - (sign >> 15), sign >> 15, 1));
4388  return half(detail::binary, detail::erf<half::round_style, true>(arg.data_));
4389 #endif
4390 }
4391 
4401 inline half lgamma(half arg)
4402 {
4403 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4404  return half(detail::binary,
4405  detail::float2half<half::round_style>(std::lgamma(detail::half2float<detail::internal_t>(arg.data_))));
4406 #else
4407  int abs = arg.data_ & 0x7FFF;
4408  if (abs >= 0x7C00)
4409  return half(detail::binary, (abs == 0x7C00) ? 0x7C00 : detail::signal(arg.data_));
4410  if (!abs || arg.data_ >= 0xE400 || (arg.data_ >= 0xBC00 && !(abs & ((1 << (25 - (abs >> 10))) - 1))))
4411  return half(detail::binary, detail::pole());
4412  if (arg.data_ == 0x3C00 || arg.data_ == 0x4000)
4413  return half(detail::binary, 0);
4414  return half(detail::binary, detail::gamma<half::round_style, true>(arg.data_));
4415 #endif
4416 }
4417 
4427 inline half tgamma(half arg)
4428 {
4429 #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
4430  return half(detail::binary,
4431  detail::float2half<half::round_style>(std::tgamma(detail::half2float<detail::internal_t>(arg.data_))));
4432 #else
4433  unsigned int abs = arg.data_ & 0x7FFF;
4434  if (!abs)
4435  return half(detail::binary, detail::pole(arg.data_));
4436  if (abs >= 0x7C00)
4437  return (arg.data_ == 0x7C00) ? arg : half(detail::binary, detail::signal(arg.data_));
4438  if (arg.data_ >= 0xE400 || (arg.data_ >= 0xBC00 && !(abs & ((1 << (25 - (abs >> 10))) - 1))))
4439  return half(detail::binary, detail::invalid());
4440  if (arg.data_ >= 0xCA80)
4441  return half(
4442  detail::binary, detail::underflow<half::round_style>((1 - ((abs >> (25 - (abs >> 10))) & 1)) << 15));
4443  if (arg.data_ <= 0x100 || (arg.data_ >= 0x4900 && arg.data_ < 0x8000))
4444  return half(detail::binary, detail::overflow<half::round_style>());
4445  if (arg.data_ == 0x3C00)
4446  return arg;
4447  return half(detail::binary, detail::gamma<half::round_style, false>(arg.data_));
4448 #endif
4449 }
4450 
4455 
4462 inline half ceil(half arg)
4463 {
4464  return half(detail::binary, detail::integral<std::round_toward_infinity, true, true>(arg.data_));
4465 }
4466 
4473 inline half floor(half arg)
4474 {
4475  return half(detail::binary, detail::integral<std::round_toward_neg_infinity, true, true>(arg.data_));
4476 }
4477 
4484 inline half trunc(half arg)
4485 {
4486  return half(detail::binary, detail::integral<std::round_toward_zero, true, true>(arg.data_));
4487 }
4488 
4495 inline half round(half arg)
4496 {
4497  return half(detail::binary, detail::integral<std::round_to_nearest, false, true>(arg.data_));
4498 }
4499 
4505 inline long lround(half arg) { return detail::half2int<std::round_to_nearest, false, false, long>(arg.data_); }
4506 
4513 inline half rint(half arg) { return half(detail::binary, detail::integral<half::round_style, true, true>(arg.data_)); }
4514 
4521 inline long lrint(half arg) { return detail::half2int<half::round_style, true, true, long>(arg.data_); }
4522 
4528 inline half nearbyint(half arg)
4529 {
4530  return half(detail::binary, detail::integral<half::round_style, true, false>(arg.data_));
4531 }
4532 #if HALF_ENABLE_CPP11_LONG_LONG
4538 inline long long llround(half arg)
4539 {
4540  return detail::half2int<std::round_to_nearest, false, false, long long>(arg.data_);
4541 }
4542 
4549 inline long long llrint(half arg) { return detail::half2int<half::round_style, true, true, long long>(arg.data_); }
4550 #endif
4551 
4556 
4563 inline half frexp(half arg, int* exp)
4564 {
4565  *exp = 0;
4566  unsigned int abs = arg.data_ & 0x7FFF;
4567  if (abs >= 0x7C00 || !abs)
4568  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
4569  for (; abs < 0x400; abs <<= 1, --*exp)
4570  ;
4571  *exp += (abs >> 10) - 14;
4572  return half(detail::binary, (arg.data_ & 0x8000) | 0x3800 | (abs & 0x3FF));
4573 }
4574 
4584 inline half scalbln(half arg, long exp)
4585 {
4586  unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
4587  if (abs >= 0x7C00 || !abs)
4588  return (abs > 0x7C00) ? half(detail::binary, detail::signal(arg.data_)) : arg;
4589  for (; abs < 0x400; abs <<= 1, --exp)
4590  ;
4591  exp += abs >> 10;
4592  if (exp > 30)
4593  return half(detail::binary, detail::overflow<half::round_style>(sign));
4594  else if (exp < -10)
4595  return half(detail::binary, detail::underflow<half::round_style>(sign));
4596  else if (exp > 0)
4597  return half(detail::binary, sign | (exp << 10) | (abs & 0x3FF));
4598  unsigned int m = (abs & 0x3FF) | 0x400;
4599  return half(detail::binary,
4600  detail::rounded<half::round_style, false>(
4601  sign | (m >> (1 - exp)), (m >> -exp) & 1, (m & ((1 << -exp) - 1)) != 0));
4602 }
4603 
4613 inline half scalbn(half arg, int exp) { return scalbln(arg, exp); }
4614 
4624 inline half ldexp(half arg, int exp) { return scalbln(arg, exp); }
4625 
4632 inline half modf(half arg, half* iptr)
4633 {
4634  unsigned int abs = arg.data_ & 0x7FFF;
4635  if (abs > 0x7C00) {
4636  arg = half(detail::binary, detail::signal(arg.data_));
4637  return *iptr = arg, arg;
4638  }
4639  if (abs >= 0x6400)
4640  return *iptr = arg, half(detail::binary, arg.data_ & 0x8000);
4641  if (abs < 0x3C00)
4642  return iptr->data_ = arg.data_ & 0x8000, arg;
4643  unsigned int exp = abs >> 10, mask = (1 << (25 - exp)) - 1, m = arg.data_ & mask;
4644  iptr->data_ = arg.data_ & ~mask;
4645  if (!m)
4646  return half(detail::binary, arg.data_ & 0x8000);
4647  for (; m < 0x400; m <<= 1, --exp)
4648  ;
4649  return half(detail::binary, (arg.data_ & 0x8000) | (exp << 10) | (m & 0x3FF));
4650 }
4651 
4660 inline int ilogb(half arg)
4661 {
4662  int abs = arg.data_ & 0x7FFF, exp;
4663  if (!abs || abs >= 0x7C00) {
4665  return !abs ? FP_ILOGB0 : (abs == 0x7C00) ? INT_MAX : FP_ILOGBNAN;
4666  }
4667  for (exp = (abs >> 10) - 15; abs < 0x200; abs <<= 1, --exp)
4668  ;
4669  return exp;
4670 }
4671 
4678 inline half logb(half arg)
4679 {
4680  int abs = arg.data_ & 0x7FFF, exp;
4681  if (!abs)
4682  return half(detail::binary, detail::pole(0x8000));
4683  if (abs >= 0x7C00)
4684  return half(detail::binary, (abs == 0x7C00) ? 0x7C00 : detail::signal(arg.data_));
4685  for (exp = (abs >> 10) - 15; abs < 0x200; abs <<= 1, --exp)
4686  ;
4687  unsigned int value = static_cast<unsigned>(exp < 0) << 15;
4688  if (exp) {
4689  unsigned int m = std::abs(exp) << 6;
4690  for (exp = 18; m < 0x400; m <<= 1, --exp)
4691  ;
4692  value |= (exp << 10) + m;
4693  }
4694  return half(detail::binary, value);
4695 }
4696 
4705 inline half nextafter(half from, half to)
4706 {
4707  int fabs = from.data_ & 0x7FFF, tabs = to.data_ & 0x7FFF;
4708  if (fabs > 0x7C00 || tabs > 0x7C00)
4709  return half(detail::binary, detail::signal(from.data_, to.data_));
4710  if (from.data_ == to.data_ || !(fabs | tabs))
4711  return to;
4712  if (!fabs) {
4714  return half(detail::binary, (to.data_ & 0x8000) + 1);
4715  }
4716  unsigned int out = from.data_ +
4717  (((from.data_ >> 15) ^
4718  static_cast<unsigned>((from.data_ ^ (0x8000 | (0x8000 - (from.data_ >> 15)))) <
4719  (to.data_ ^ (0x8000 | (0x8000 - (to.data_ >> 15))))))
4720  << 1) -
4721  1;
4722  detail::raise(FE_OVERFLOW, fabs < 0x7C00 && (out & 0x7C00) == 0x7C00);
4724  return half(detail::binary, out);
4725 }
4726 
4735 inline half nexttoward(half from, long double to)
4736 {
4737  int fabs = from.data_ & 0x7FFF;
4738  if (fabs > 0x7C00)
4739  return half(detail::binary, detail::signal(from.data_));
4740  long double lfrom = static_cast<long double>(from);
4741  if (detail::builtin_isnan(to) || lfrom == to)
4742  return half(static_cast<float>(to));
4743  if (!fabs) {
4745  return half(detail::binary, (static_cast<unsigned>(detail::builtin_signbit(to)) << 15) + 1);
4746  }
4747  unsigned int out = from.data_ + (((from.data_ >> 15) ^ static_cast<unsigned>(lfrom < to)) << 1) - 1;
4748  detail::raise(FE_OVERFLOW, (out & 0x7FFF) == 0x7C00);
4750  return half(detail::binary, out);
4751 }
4752 
4759 {
4760  return half(detail::binary, x.data_ ^ ((x.data_ ^ y.data_) & 0x8000));
4761 }
4762 
4767 
4777 {
4778  return !(arg.data_ & 0x7FFF) ? FP_ZERO
4779  : ((arg.data_ & 0x7FFF) < 0x400) ? FP_SUBNORMAL
4780  : ((arg.data_ & 0x7FFF) < 0x7C00) ? FP_NORMAL
4781  : ((arg.data_ & 0x7FFF) == 0x7C00) ? FP_INFINITE
4782  : FP_NAN;
4783 }
4784 
4790 inline HALF_CONSTEXPR bool isfinite(half arg) { return (arg.data_ & 0x7C00) != 0x7C00; }
4791 
4797 inline HALF_CONSTEXPR bool isinf(half arg) { return (arg.data_ & 0x7FFF) == 0x7C00; }
4798 
4804 inline HALF_CONSTEXPR bool isnan(half arg) { return (arg.data_ & 0x7FFF) > 0x7C00; }
4805 
4811 inline HALF_CONSTEXPR bool isnormal(half arg) { return ((arg.data_ & 0x7C00) != 0) & ((arg.data_ & 0x7C00) != 0x7C00); }
4812 
4818 inline HALF_CONSTEXPR bool signbit(half arg) { return (arg.data_ & 0x8000) != 0; }
4819 
4824 
4832 {
4833  return ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) >
4834  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15)) &&
4835  !isnan(x) && !isnan(y);
4836 }
4837 
4843 {
4844  return ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) >=
4845  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15)) &&
4846  !isnan(x) && !isnan(y);
4847 }
4848 
4855 inline HALF_CONSTEXPR bool isless(half x, half y)
4856 {
4857  return ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) <
4858  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15)) &&
4859  !isnan(x) && !isnan(y);
4860 }
4861 
4869 {
4870  return ((x.data_ ^ (0x8000 | (0x8000 - (x.data_ >> 15)))) + (x.data_ >> 15)) <=
4871  ((y.data_ ^ (0x8000 | (0x8000 - (y.data_ >> 15)))) + (y.data_ >> 15)) &&
4872  !isnan(x) && !isnan(y);
4873 }
4874 
4882 {
4883  return x.data_ != y.data_ && ((x.data_ | y.data_) & 0x7FFF) && !isnan(x) && !isnan(y);
4884 }
4885 
4892 inline HALF_CONSTEXPR bool isunordered(half x, half y) { return isnan(x) || isnan(y); }
4893 
4898 
4913 template <typename T, typename U> T half_cast(U arg) { return detail::half_caster<T, U>::cast(arg); }
4914 
4930 template <typename T, std::float_round_style R, typename U> T half_cast(U arg)
4931 {
4933 }
4935 
4940 
4948 inline int feclearexcept(int excepts)
4949 {
4950  detail::errflags() &= ~excepts;
4951  return 0;
4952 }
4953 
4961 inline int fetestexcept(int excepts) { return detail::errflags() & excepts; }
4962 
4972 inline int feraiseexcept(int excepts)
4973 {
4974  detail::errflags() |= excepts;
4975  detail::raise(excepts);
4976  return 0;
4977 }
4978 
4987 inline int fegetexceptflag(int* flagp, int excepts)
4988 {
4989  *flagp = detail::errflags() & excepts;
4990  return 0;
4991 }
4992 
5002 inline int fesetexceptflag(const int* flagp, int excepts)
5003 {
5004  detail::errflags() = (detail::errflags() | (*flagp & excepts)) & (*flagp | ~excepts);
5005  return 0;
5006 }
5007 
5019 inline void fethrowexcept(int excepts, const char* msg = "")
5020 {
5021  excepts &= detail::errflags();
5022  if (excepts & (FE_INVALID | FE_DIVBYZERO))
5023  throw std::domain_error(msg);
5024  if (excepts & FE_OVERFLOW)
5025  throw std::overflow_error(msg);
5026  if (excepts & FE_UNDERFLOW)
5027  throw std::underflow_error(msg);
5028  if (excepts & FE_INEXACT)
5029  throw std::range_error(msg);
5030 }
5032 } // namespace half_float
5033 
5034 #undef HALF_UNUSED_NOERR
5035 #undef HALF_CONSTEXPR
5036 #undef HALF_CONSTEXPR_CONST
5037 #undef HALF_CONSTEXPR_NOERR
5038 #undef HALF_NOEXCEPT
5039 #undef HALF_NOTHROW
5040 #undef HALF_THREAD_LOCAL
5041 #undef HALF_TWOS_COMPLEMENT_INT
5042 #ifdef HALF_POP_WARNINGS
5043 #pragma warning(pop)
5044 #undef HALF_POP_WARNINGS
5045 #endif
5046 
5047 #endif
Half-precision floating-point type.
Definition: half.hpp:2222
friend half asinh(half)
Hyperbolic area sine.
Definition: half.hpp:4252
friend void sincos(half, half *, half *)
Compute sine and cosine simultaneously.
Definition: half.hpp:3816
friend half exp2(half)
Binary exponential.
Definition: half.hpp:3236
half operator++(int)
Postfix increment.
Definition: half.hpp:2327
friend half tanh(half)
Hyperbolic tangent.
Definition: half.hpp:4217
friend std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &, half)
Output operator.
Definition: half.hpp:2929
friend long lrint(half)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4521
friend half nanh(const char *)
Get NaN value.
Definition: half.hpp:3180
friend half atanh(half)
Hyperbolic area tangent.
Definition: half.hpp:4308
friend half atan(half)
Arc tangent function.
Definition: half.hpp:4056
friend half tan(half)
Tangent function.
Definition: half.hpp:3952
friend half nearbyint(half)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4528
friend half log1p(half)
Natural logarithm plus one.
Definition: half.hpp:3440
friend half pow(half, half)
Power function.
Definition: half.hpp:3738
half & operator-=(float rhs)
Arithmetic assignment.
Definition: half.hpp:2296
half & operator=(float rhs)
Assignment operator.
Definition: half.hpp:2248
friend half remquo(half, half, int *)
Remainder of division.
Definition: half.hpp:3028
HALF_CONSTEXPR half() HALF_NOEXCEPT
Default constructor.
Definition: half.hpp:2230
half & operator--()
Prefix decrement.
Definition: half.hpp:2322
friend half sqrt(half)
Square root.
Definition: half.hpp:3490
friend half ceil(half)
Nearest integer not less than half value.
Definition: half.hpp:4462
friend half erf(half)
Error function.
Definition: half.hpp:4349
friend half atan2(half, half)
Arc tangent function.
Definition: half.hpp:4090
half & operator/=(float rhs)
Arithmetic assignment.
Definition: half.hpp:2308
friend half modf(half, half *)
Extract integer and fractional parts.
Definition: half.hpp:4632
friend half operator*(half, half)
Multiplication.
Definition: half.hpp:2842
HALF_CONSTEXPR half(detail::binary_t, unsigned int bits) HALF_NOEXCEPT
Constructor.
Definition: half.hpp:2351
friend half sin(half)
Sine function.
Definition: half.hpp:3885
friend half trunc(half)
Nearest integer not greater in magnitude than half value.
Definition: half.hpp:4484
friend half nexttoward(half, long double)
Next representable value.
Definition: half.hpp:4735
friend half lgamma(half)
Natural logarithm of gamma function.
Definition: half.hpp:4401
friend HALF_CONSTEXPR bool isgreaterequal(half, half)
Quiet comparison for greater equal.
Definition: half.hpp:4842
friend half nextafter(half, half)
Next representable value.
Definition: half.hpp:4705
friend HALF_CONSTEXPR half copysign(half, half)
Take sign.
Definition: half.hpp:4758
friend half operator/(half, half)
Division.
Definition: half.hpp:2882
friend half tgamma(half)
Gamma function.
Definition: half.hpp:4427
half & operator/=(half rhs)
Arithmetic assignment.
Definition: half.hpp:2284
friend half exp(half)
Exponential function.
Definition: half.hpp:3201
friend HALF_CONSTEXPR half operator-(half)
Negation.
Definition: half.hpp:2757
friend half log10(half)
Common logarithm.
Definition: half.hpp:3349
friend HALF_CONSTEXPR bool isnan(half)
Check for NaN.
Definition: half.hpp:4804
friend half scalbln(half, long)
Multiply by power of two.
Definition: half.hpp:4584
friend half frexp(half, int *)
Decompress floating-point number.
Definition: half.hpp:4563
friend half cbrt(half)
Cubic root.
Definition: half.hpp:3563
friend half log(half)
Natural logarithm.
Definition: half.hpp:3318
friend HALF_CONSTEXPR half fabs(half)
Absolute value.
Definition: half.hpp:2969
friend HALF_CONSTEXPR bool islessgreater(half, half)
Quiet comarison for less or greater.
Definition: half.hpp:4881
friend HALF_CONSTEXPR bool isnormal(half)
Check if normal number.
Definition: half.hpp:4811
friend half fdim(half, half)
Positive difference.
Definition: half.hpp:3167
friend HALF_CONSTEXPR int fpclassify(half)
Classify floating-point value.
Definition: half.hpp:4776
half & operator*=(half rhs)
Arithmetic assignment.
Definition: half.hpp:2277
friend HALF_CONSTEXPR_NOERR bool operator==(half, half)
Comparison for equality.
Definition: half.hpp:2676
friend half cos(half)
Cosine function.
Definition: half.hpp:3922
detail::uint16 data_
Internal binary representation.
Definition: half.hpp:2354
half & operator+=(float rhs)
Arithmetic assignment.
Definition: half.hpp:2290
half & operator+=(half rhs)
Arithmetic assignment.
Definition: half.hpp:2263
friend HALF_CONSTEXPR bool isfinite(half)
Check if finite number.
Definition: half.hpp:4790
friend half rsqrt(half)
Inverse square root.
Definition: half.hpp:3517
friend HALF_CONSTEXPR bool isgreater(half, half)
Quiet comparison for greater than.
Definition: half.hpp:4831
friend half fmod(half, half)
Remainder of division.
Definition: half.hpp:2983
half(float rhs)
Conversion constructor.
Definition: half.hpp:2235
friend HALF_CONSTEXPR bool signbit(half)
Check sign.
Definition: half.hpp:4818
friend half acos(half)
Arc cosine function.
Definition: half.hpp:4026
half & operator*=(float rhs)
Arithmetic assignment.
Definition: half.hpp:2302
friend half remainder(half, half)
Remainder of division.
Definition: half.hpp:3006
friend half cosh(half)
Hyperbolic cosine.
Definition: half.hpp:4188
friend HALF_CONSTEXPR_NOERR half fmax(half, half)
Maximum of half expressions.
Definition: half.hpp:3133
friend long lround(half)
Nearest integer.
Definition: half.hpp:4505
friend HALF_CONSTEXPR_NOERR bool operator<=(half, half)
Comparison for less equal.
Definition: half.hpp:2724
friend std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &, half &)
Input operator.
Definition: half.hpp:2948
friend half acosh(half)
Hyperbolic area cosine.
Definition: half.hpp:4282
friend half log2(half)
Binary logarithm.
Definition: half.hpp:3390
friend half round(half)
Nearest integer.
Definition: half.hpp:4495
friend HALF_CONSTEXPR bool isless(half, half)
Quiet comparison for less than.
Definition: half.hpp:4855
friend half expm1(half)
Exponential minus one.
Definition: half.hpp:3265
friend HALF_CONSTEXPR_NOERR bool operator>=(half, half)
Comparison for greater equal.
Definition: half.hpp:2737
friend half hypot(half, half)
Hypotenuse function.
Definition: half.hpp:3617
half & operator-=(half rhs)
Arithmetic assignment.
Definition: half.hpp:2270
friend HALF_CONSTEXPR_NOERR bool operator!=(half, half)
Comparison for inequality.
Definition: half.hpp:2687
half & operator++()
Prefix increment.
Definition: half.hpp:2317
friend HALF_CONSTEXPR_NOERR bool operator<(half, half)
Comparison for less than.
Definition: half.hpp:2698
friend half erfc(half)
Complementary error function.
Definition: half.hpp:4374
friend half operator+(half, half)
Addition.
Definition: half.hpp:2766
friend half floor(half)
Nearest integer not greater than half value.
Definition: half.hpp:4473
friend HALF_CONSTEXPR_NOERR half fmin(half, half)
Minimum of half expressions.
Definition: half.hpp:3149
half operator--(int)
Postfix decrement.
Definition: half.hpp:2337
friend HALF_CONSTEXPR bool isinf(half)
Check for infinity.
Definition: half.hpp:4797
friend int ilogb(half)
Extract exponent.
Definition: half.hpp:4660
friend half fma(half, half, half)
Fused multiply add.
Definition: half.hpp:3055
friend half sinh(half)
Hyperbolic sine.
Definition: half.hpp:4157
friend half rint(half)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4513
friend HALF_CONSTEXPR bool islessequal(half, half)
Quiet comparison for less equal.
Definition: half.hpp:4868
friend half asin(half)
Arc sine.
Definition: half.hpp:3994
friend half logb(half)
Extract exponent.
Definition: half.hpp:4678
static const std::float_round_style round_style
Rounding mode to use.
Definition: half.hpp:2347
friend HALF_CONSTEXPR_NOERR bool operator>(half, half)
Comparison for greater than.
Definition: half.hpp:2711
static HALF_CONSTEXPR half_float::half max() HALF_NOTHROW
Largest finite value.
Definition: half.hpp:2600
static HALF_CONSTEXPR half_float::half quiet_NaN() HALF_NOTHROW
Quiet NaN.
Definition: half.hpp:2624
static HALF_CONSTEXPR half_float::half min() HALF_NOTHROW
Smallest positive normal value.
Definition: half.hpp:2588
static HALF_CONSTEXPR half_float::half round_error() HALF_NOTHROW
Maximum rounding error in ULP (units in the last place).
Definition: half.hpp:2612
static HALF_CONSTEXPR half_float::half infinity() HALF_NOTHROW
Positive infinity.
Definition: half.hpp:2618
static HALF_CONSTEXPR half_float::half epsilon() HALF_NOTHROW
Difference between 1 and next representable value.
Definition: half.hpp:2606
static HALF_CONSTEXPR half_float::half lowest() HALF_NOTHROW
Smallest finite value.
Definition: half.hpp:2594
static HALF_CONSTEXPR half_float::half signaling_NaN() HALF_NOTHROW
Signaling NaN.
Definition: half.hpp:2630
static HALF_CONSTEXPR half_float::half denorm_min() HALF_NOTHROW
Smallest positive subnormal value.
Definition: half.hpp:2636
#define FP_ILOGBNAN
Definition: half.hpp:415
#define HALF_NOEXCEPT
Definition: half.hpp:237
#define FP_NAN
Definition: half.hpp:424
#define HALF_CONSTEXPR_NOERR
Definition: half.hpp:229
#define FP_ZERO
Definition: half.hpp:421
#define FP_INFINITE
Definition: half.hpp:427
#define FE_UNDERFLOW
Definition: half.hpp:437
#define HALF_CONSTEXPR_CONST
Definition: half.hpp:228
#define FE_INVALID
Definition: half.hpp:434
#define FE_INEXACT
Definition: half.hpp:438
#define HALF_THREAD_LOCAL
Definition: half.hpp:245
#define HALF_NOTHROW
Definition: half.hpp:238
#define FP_ILOGB0
Definition: half.hpp:412
#define HALF_UNUSED_NOERR(name)
Definition: half.hpp:214
#define FE_DIVBYZERO
Definition: half.hpp:435
#define FP_NORMAL
Definition: half.hpp:430
#define HALF_CONSTEXPR
Definition: half.hpp:227
#define FE_OVERFLOW
Definition: half.hpp:436
#define FP_SUBNORMAL
Definition: half.hpp:418
#define HALF_ROUND_STYLE
Default rounding mode.
Definition: half.hpp:387
#define HALF_ERRHANDLING_UNDERFLOW_TO_INEXACT
Raise INEXACT exception on underflow.
Definition: half.hpp:363
bool_type< false > false_type
Definition: half.hpp:489
HALF_CONSTEXPR_CONST binary_t binary
Tag for binary construction.
Definition: half.hpp:576
std::pair< uint32, uint32 > hyperbolic_args(unsigned int abs, int &exp, unsigned int n=32)
Get exponentials for hyperbolic computation.
Definition: half.hpp:1826
unsigned int integral(unsigned int value)
Round half-precision number to nearest integer value.
Definition: half.hpp:898
uint32 exp2(uint32 m, unsigned int n=32)
Fixed point binary exponential.
Definition: half.hpp:1676
bool builtin_signbit(T arg)
Check sign.
Definition: half.hpp:618
unsigned int hypot_post(uint32 r, int exp)
Hypotenuse square root and postprocessing.
Definition: half.hpp:1918
int & errflags()
Internal exception flags.
Definition: half.hpp:661
bool builtin_isnan(T arg)
Check for NaN.
Definition: half.hpp:602
unsigned short uint16
Unsigned integer of (at least) 16 bits width.
Definition: half.hpp:540
std::pair< uint32, uint32 > atan2_args(unsigned int abs)
Get arguments for atan2 function.
Definition: half.hpp:1798
HALF_CONSTEXPR_NOERR unsigned int check_underflow(unsigned int arg)
Check value for underflow.
Definition: half.hpp:814
unsigned int fixed2half(uint32 m, int exp=14, unsigned int sign=0, int s=0)
Convert fixed point to half-precision floating-point.
Definition: half.hpp:936
unsigned int mod(unsigned int x, unsigned int y, int *quo=NULL)
Half precision positive modulus.
Definition: half.hpp:1589
uint32 sqrt(uint32 &r, int &exp)
Fixed point square root.
Definition: half.hpp:1654
HALF_CONSTEXPR_NOERR unsigned int select(unsigned int x, unsigned int HALF_UNUSED_NOERR(y))
Select value or signaling NaN.
Definition: half.hpp:778
float half2float_impl(unsigned int value, float, true_type)
Convert half-precision to IEEE single-precision.
Definition: half.hpp:1164
HALF_CONSTEXPR_NOERR unsigned int overflow(unsigned int sign=0)
Half-precision overflow.
Definition: half.hpp:831
uint32 multiply64(uint32 x, uint32 y)
64-bit multiplication.
Definition: half.hpp:1547
T half2int(unsigned int value)
Convert half-precision floating-point to integer.
Definition: half.hpp:1492
uint32 mulhi(uint32 x, uint32 y)
upper part of 64-bit multiplication.
Definition: half.hpp:1533
bool_type< true > true_type
Definition: half.hpp:488
HALF_CONSTEXPR_NOERR bool compsignal(unsigned int x, unsigned int y)
Check and signal for any NaN.
Definition: half.hpp:724
uint32 atan2(uint32 my, uint32 mx, unsigned int n=31)
Fixed point arc tangent.
Definition: half.hpp:1748
long int32
Fastest unsigned integer of (at least) 32 bits width.
Definition: half.hpp:546
unsigned int float2half(T value)
Convert floating-point to half-precision.
Definition: half.hpp:1128
HALF_CONSTEXPR_NOERR unsigned int underflow(unsigned int sign=0)
Half-precision underflow.
Definition: half.hpp:847
HALF_CONSTEXPR_NOERR unsigned int signal(unsigned int nan)
Signal and silence signaling NaN.
Definition: half.hpp:736
HALF_CONSTEXPR_NOERR unsigned int invalid()
Raise domain error and return NaN.
Definition: half.hpp:790
unsigned int gamma(unsigned int arg)
Gamma function and postprocessing.
Definition: half.hpp:2117
std::pair< uint32, uint32 > sincos(uint32 mz, unsigned int n=31)
Fixed point sine and cosine.
Definition: half.hpp:1724
uint32 arithmetic_shift(uint32 arg, int i)
Platform-independent arithmetic right shift.
Definition: half.hpp:645
uint32 log2(uint32 m, unsigned int n=32)
Fixed point binary logarithm.
Definition: half.hpp:1700
T half2float(unsigned int value)
Convert half-precision to floating-point.
Definition: half.hpp:1479
uint32 divide64(uint32 x, uint32 y, int &s)
64-bit division.
Definition: half.hpp:1562
void raise(int HALF_UNUSED_NOERR(flags), bool HALF_UNUSED_NOERR(cond)=true)
Raise floating-point exception.
Definition: half.hpp:670
uint32 angle_arg(unsigned int abs, int &k)
Reduce argument for trigonometric functions.
Definition: half.hpp:1770
unsigned int log2_post(uint32 m, int ilog, int exp, unsigned int sign=0)
Postprocessing for binary logarithm.
Definition: half.hpp:1892
unsigned int area(unsigned int arg)
Area function and postprocessing.
Definition: half.hpp:1961
HALF_CONSTEXPR_NOERR unsigned int rounded(unsigned int value, int g, int s)
Round half-precision number.
Definition: half.hpp:868
unsigned long uint32
Fastest unsigned integer of (at least) 32 bits width.
Definition: half.hpp:543
unsigned int float2half_impl(float value, true_type)
Convert IEEE single-precision to half-precision.
Definition: half.hpp:961
uint32 sign_mask(uint32 arg)
Platform-independent sign mask.
Definition: half.hpp:631
bool builtin_isinf(T arg)
Check for infinity.
Definition: half.hpp:586
unsigned int erf(unsigned int arg)
Error function and postprocessing.
Definition: half.hpp:2092
unsigned int int2half(T value)
Convert integer to half-precision floating-point.
Definition: half.hpp:1141
unsigned int tangent_post(uint32 my, uint32 mx, int exp, unsigned int sign=0)
Division and postprocessing for tangents.
Definition: half.hpp:1940
unsigned int exp2_post(uint32 m, int exp, bool esign, unsigned int sign=0, unsigned int n=32)
Postprocessing for binary exponential.
Definition: half.hpp:1861
HALF_CONSTEXPR_NOERR unsigned int pole(unsigned int sign=0)
Raise pole error and return infinity.
Definition: half.hpp:802
Main namespace for half-precision functionality.
Definition: half.hpp:444
half asinh(half arg)
Hyperbolic area sine.
Definition: half.hpp:4252
half sinh(half arg)
Hyperbolic sine.
Definition: half.hpp:4157
int feclearexcept(int excepts)
Clear exception flags.
Definition: half.hpp:4948
HALF_CONSTEXPR half fabs(half arg)
Absolute value.
Definition: half.hpp:2969
half nextafter(half from, half to)
Next representable value.
Definition: half.hpp:4705
half atan(half arg)
Arc tangent function.
Definition: half.hpp:4056
half hypot(half x, half y)
Hypotenuse function.
Definition: half.hpp:3617
HALF_CONSTEXPR bool isunordered(half x, half y)
Quiet check if unordered.
Definition: half.hpp:4892
half fdim(half x, half y)
Positive difference.
Definition: half.hpp:3167
half remquo(half x, half y, int *quo)
Remainder of division.
Definition: half.hpp:3028
int fegetexceptflag(int *flagp, int excepts)
Save exception flags.
Definition: half.hpp:4987
int ilogb(half arg)
Extract exponent.
Definition: half.hpp:4660
half lgamma(half arg)
Natural logarithm of gamma function.
Definition: half.hpp:4401
HALF_CONSTEXPR half copysign(half x, half y)
Take sign.
Definition: half.hpp:4758
HALF_CONSTEXPR bool isfinite(half arg)
Check if finite number.
Definition: half.hpp:4790
int fesetexceptflag(const int *flagp, int excepts)
Restore exception flags.
Definition: half.hpp:5002
HALF_CONSTEXPR half abs(half arg)
Absolute value.
Definition: half.hpp:2975
half fma(half x, half y, half z)
Fused multiply add.
Definition: half.hpp:3055
HALF_CONSTEXPR_NOERR half fmin(half x, half y)
Minimum of half expressions.
Definition: half.hpp:3149
half nearbyint(half arg)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4528
half expm1(half arg)
Exponential minus one.
Definition: half.hpp:3265
half ldexp(half arg, int exp)
Multiply by power of two.
Definition: half.hpp:4624
half sin(half arg)
Sine function.
Definition: half.hpp:3885
half tanh(half arg)
Hyperbolic tangent.
Definition: half.hpp:4217
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &in, half &arg)
Input operator.
Definition: half.hpp:2948
half rint(half arg)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4513
HALF_CONSTEXPR_NOERR bool operator!=(half x, half y)
Comparison for inequality.
Definition: half.hpp:2687
HALF_CONSTEXPR_NOERR half fmax(half x, half y)
Maximum of half expressions.
Definition: half.hpp:3133
HALF_CONSTEXPR_NOERR bool operator<(half x, half y)
Comparison for less than.
Definition: half.hpp:2698
HALF_CONSTEXPR half operator-(half arg)
Negation.
Definition: half.hpp:2757
T half_cast(U arg)
Cast to or from half-precision floating-point number.
Definition: half.hpp:4913
half fmod(half x, half y)
Remainder of division.
Definition: half.hpp:2983
half log(half arg)
Natural logarithm.
Definition: half.hpp:3318
half cos(half arg)
Cosine function.
Definition: half.hpp:3922
half scalbn(half arg, int exp)
Multiply by power of two.
Definition: half.hpp:4613
half exp2(half arg)
Binary exponential.
Definition: half.hpp:3236
HALF_CONSTEXPR int fpclassify(half arg)
Classify floating-point value.
Definition: half.hpp:4776
HALF_CONSTEXPR_NOERR bool operator>=(half x, half y)
Comparison for greater equal.
Definition: half.hpp:2737
half atanh(half arg)
Hyperbolic area tangent.
Definition: half.hpp:4308
half nexttoward(half from, long double to)
Next representable value.
Definition: half.hpp:4735
half round(half arg)
Nearest integer.
Definition: half.hpp:4495
half log2(half arg)
Binary logarithm.
Definition: half.hpp:3390
HALF_CONSTEXPR bool isgreater(half x, half y)
Quiet comparison for greater than.
Definition: half.hpp:4831
half asin(half arg)
Arc sine.
Definition: half.hpp:3994
half sqrt(half arg)
Square root.
Definition: half.hpp:3490
half trunc(half arg)
Nearest integer not greater in magnitude than half value.
Definition: half.hpp:4484
half erfc(half arg)
Complementary error function.
Definition: half.hpp:4374
half tan(half arg)
Tangent function.
Definition: half.hpp:3952
HALF_CONSTEXPR half operator+(half arg)
Identity.
Definition: half.hpp:2752
half log10(half arg)
Common logarithm.
Definition: half.hpp:3349
half rsqrt(half arg)
Inverse square root.
Definition: half.hpp:3517
HALF_CONSTEXPR bool signbit(half arg)
Check sign.
Definition: half.hpp:4818
half floor(half arg)
Nearest integer not greater than half value.
Definition: half.hpp:4473
half acosh(half arg)
Hyperbolic area cosine.
Definition: half.hpp:4282
HALF_CONSTEXPR bool isnan(half arg)
Check for NaN.
Definition: half.hpp:4804
HALF_CONSTEXPR_NOERR bool operator<=(half x, half y)
Comparison for less equal.
Definition: half.hpp:2724
half operator*(half x, half y)
Multiplication.
Definition: half.hpp:2842
HALF_CONSTEXPR bool isnormal(half arg)
Check if normal number.
Definition: half.hpp:4811
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &out, half arg)
Output operator.
Definition: half.hpp:2929
half atan2(half y, half x)
Arc tangent function.
Definition: half.hpp:4090
int feraiseexcept(int excepts)
Raise exception flags.
Definition: half.hpp:4972
HALF_CONSTEXPR bool isless(half x, half y)
Quiet comparison for less than.
Definition: half.hpp:4855
half scalbln(half arg, long exp)
Multiply by power of two.
Definition: half.hpp:4584
half tgamma(half arg)
Gamma function.
Definition: half.hpp:4427
HALF_CONSTEXPR_NOERR bool operator==(half x, half y)
Comparison for equality.
Definition: half.hpp:2676
long lrint(half arg)
Nearest integer using half's internal rounding mode.
Definition: half.hpp:4521
HALF_CONSTEXPR bool isinf(half arg)
Check for infinity.
Definition: half.hpp:4797
HALF_CONSTEXPR_NOERR bool operator>(half x, half y)
Comparison for greater than.
Definition: half.hpp:2711
half cosh(half arg)
Hyperbolic cosine.
Definition: half.hpp:4188
half logb(half arg)
Extract exponent.
Definition: half.hpp:4678
half erf(half arg)
Error function.
Definition: half.hpp:4349
void sincos(half arg, half *sin, half *cos)
Compute sine and cosine simultaneously.
Definition: half.hpp:3816
half ceil(half arg)
Nearest integer not less than half value.
Definition: half.hpp:4462
half frexp(half arg, int *exp)
Decompress floating-point number.
Definition: half.hpp:4563
half log1p(half arg)
Natural logarithm plus one.
Definition: half.hpp:3440
HALF_CONSTEXPR bool islessgreater(half x, half y)
Quiet comarison for less or greater.
Definition: half.hpp:4881
half hypot(half x, half y, half z)
Hypotenuse function.
Definition: half.hpp:3668
long lround(half arg)
Nearest integer.
Definition: half.hpp:4505
half acos(half arg)
Arc cosine function.
Definition: half.hpp:4026
HALF_CONSTEXPR bool islessequal(half x, half y)
Quiet comparison for less equal.
Definition: half.hpp:4868
half pow(half x, half y)
Power function.
Definition: half.hpp:3738
half nanh(const char *arg)
Get NaN value.
Definition: half.hpp:3180
half modf(half arg, half *iptr)
Extract integer and fractional parts.
Definition: half.hpp:4632
half cbrt(half arg)
Cubic root.
Definition: half.hpp:3563
void fethrowexcept(int excepts, const char *msg="")
Throw C++ exceptions based on set exception flags.
Definition: half.hpp:5019
HALF_CONSTEXPR bool isgreaterequal(half x, half y)
Quiet comparison for greater equal.
Definition: half.hpp:4842
int fetestexcept(int excepts)
Test exception flags.
Definition: half.hpp:4961
half exp(half arg)
Exponential function.
Definition: half.hpp:3201
half remainder(half x, half y)
Remainder of division.
Definition: half.hpp:3006
half operator/(half x, half y)
Division.
Definition: half.hpp:2882
Extensions to the C++ standard library.
Definition: half.hpp:2509
MICROSOFT_QUANTUM_DECL void T(_In_ uintq sid, _In_ uintq q)
(External API) "T" Gate
Definition: pinvoke_api.cpp:1317
MICROSOFT_QUANTUM_DECL void R(_In_ uintq sid, _In_ uintq b, _In_ double phi, _In_ uintq q)
(External API) Rotation around Pauli axes
Definition: pinvoke_api.cpp:1781
MICROSOFT_QUANTUM_DECL void S(_In_ uintq sid, _In_ uintq q)
(External API) "S" Gate
Definition: pinvoke_api.cpp:1302
MICROSOFT_QUANTUM_DECL void U(_In_ uintq sid, _In_ uintq q, _In_ double theta, _In_ double phi, _In_ double lambda)
(External API) 3-parameter unitary gate
Definition: pinvoke_api.cpp:1362
Tag type for binary construction.
Definition: half.hpp:573
unsigned long type
Definition: half.hpp:562
Type traits for floating-point bits.
Definition: half.hpp:509
unsigned char type
Definition: half.hpp:510
Helper for tag dispatching.
Definition: half.hpp:486
Conditional type.
Definition: half.hpp:478
T type
Definition: half.hpp:479
Class for 1.31 unsigned floating-point computation.
Definition: half.hpp:2006
friend f31 operator-(f31 a, f31 b)
Subtraction operator.
Definition: half.hpp:2045
int exp
exponent.
Definition: half.hpp:2079
friend f31 operator*(f31 a, f31 b)
Multiplication operator.
Definition: half.hpp:2060
friend f31 operator/(f31 a, f31 b)
Division operator.
Definition: half.hpp:2071
friend f31 operator+(f31 a, f31 b)
Addition operator.
Definition: half.hpp:2031
f31(unsigned int abs)
Constructor.
Definition: half.hpp:2018
HALF_CONSTEXPR f31(uint32 mant, int e)
Constructor.
Definition: half.hpp:2010
uint32 m
mantissa as 1.31.
Definition: half.hpp:2078
static T cast_impl(half arg, true_type)
Definition: half.hpp:2499
static T cast(half arg)
Definition: half.hpp:2496
static T cast_impl(half arg, false_type)
Definition: half.hpp:2500
static half cast_impl(U arg, false_type)
Definition: half.hpp:2489
static half cast(U arg)
Definition: half.hpp:2485
static half cast_impl(U arg, true_type)
Definition: half.hpp:2488
static half cast(half arg)
Definition: half.hpp:2503
Helper class for half casts.
Definition: half.hpp:2478
Type traits for floating-point types.
Definition: half.hpp:492