1 // half - IEEE 754-based half-precision floating point library.
\r
3 // Copyright (c) 2012-2017 Christian Rau <rauy@users.sourceforge.net>
\r
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
\r
6 // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
\r
7 // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
\r
8 // Software is furnished to do so, subject to the following conditions:
\r
10 // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
\r
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
\r
13 // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
14 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
\r
15 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
20 /// Main header file for half precision functionality.
\r
22 #ifndef HALF_HALF_HPP
\r
23 #define HALF_HALF_HPP
\r
25 /// Combined gcc version number.
\r
26 #define HALF_GNUC_VERSION (__GNUC__*100+__GNUC_MINOR__)
\r
28 //check C++11 language features
\r
29 #if defined(__clang__) //clang
\r
30 #if __has_feature(cxx_static_assert) && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
\r
31 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
\r
33 #if __has_feature(cxx_constexpr) && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
\r
34 #define HALF_ENABLE_CPP11_CONSTEXPR 1
\r
36 #if __has_feature(cxx_noexcept) && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
\r
37 #define HALF_ENABLE_CPP11_NOEXCEPT 1
\r
39 #if __has_feature(cxx_user_literals) && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
\r
40 #define HALF_ENABLE_CPP11_USER_LITERALS 1
\r
42 #if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && !defined(HALF_ENABLE_CPP11_LONG_LONG)
\r
43 #define HALF_ENABLE_CPP11_LONG_LONG 1
\r
45 /*#elif defined(__INTEL_COMPILER) //Intel C++
\r
46 #if __INTEL_COMPILER >= 1100 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT) ????????
\r
47 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
\r
49 #if __INTEL_COMPILER >= 1300 && !defined(HALF_ENABLE_CPP11_CONSTEXPR) ????????
\r
50 #define HALF_ENABLE_CPP11_CONSTEXPR 1
\r
52 #if __INTEL_COMPILER >= 1300 && !defined(HALF_ENABLE_CPP11_NOEXCEPT) ????????
\r
53 #define HALF_ENABLE_CPP11_NOEXCEPT 1
\r
55 #if __INTEL_COMPILER >= 1100 && !defined(HALF_ENABLE_CPP11_LONG_LONG) ????????
\r
56 #define HALF_ENABLE_CPP11_LONG_LONG 1
\r
58 #elif defined(__GNUC__) //gcc
\r
59 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
\r
60 #if HALF_GNUC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
\r
61 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
\r
63 #if HALF_GNUC_VERSION >= 406 && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
\r
64 #define HALF_ENABLE_CPP11_CONSTEXPR 1
\r
66 #if HALF_GNUC_VERSION >= 406 && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
\r
67 #define HALF_ENABLE_CPP11_NOEXCEPT 1
\r
69 #if HALF_GNUC_VERSION >= 407 && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
\r
70 #define HALF_ENABLE_CPP11_USER_LITERALS 1
\r
72 #if !defined(HALF_ENABLE_CPP11_LONG_LONG)
\r
73 #define HALF_ENABLE_CPP11_LONG_LONG 1
\r
76 #elif defined(_MSC_VER) //Visual C++
\r
77 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_CONSTEXPR)
\r
78 #define HALF_ENABLE_CPP11_CONSTEXPR 1
\r
80 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_NOEXCEPT)
\r
81 #define HALF_ENABLE_CPP11_NOEXCEPT 1
\r
83 #if _MSC_VER >= 1900 && !defined(HALF_ENABLE_CPP11_USER_LITERALS)
\r
84 #define HALF_ENABLE_CPP11_USER_LITERALS 1
\r
86 #if _MSC_VER >= 1600 && !defined(HALF_ENABLE_CPP11_STATIC_ASSERT)
\r
87 #define HALF_ENABLE_CPP11_STATIC_ASSERT 1
\r
89 #if _MSC_VER >= 1310 && !defined(HALF_ENABLE_CPP11_LONG_LONG)
\r
90 #define HALF_ENABLE_CPP11_LONG_LONG 1
\r
92 #define HALF_POP_WARNINGS 1
\r
93 #pragma warning(push)
\r
94 #pragma warning(disable : 4099 4127 4146) //struct vs class, constant in if, negative unsigned
\r
97 //check C++11 library features
\r
99 #if defined(_LIBCPP_VERSION) //libc++
\r
100 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103
\r
101 #ifndef HALF_ENABLE_CPP11_TYPE_TRAITS
\r
102 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
\r
104 #ifndef HALF_ENABLE_CPP11_CSTDINT
\r
105 #define HALF_ENABLE_CPP11_CSTDINT 1
\r
107 #ifndef HALF_ENABLE_CPP11_CMATH
\r
108 #define HALF_ENABLE_CPP11_CMATH 1
\r
110 #ifndef HALF_ENABLE_CPP11_HASH
\r
111 #define HALF_ENABLE_CPP11_HASH 1
\r
114 #elif defined(__GLIBCXX__) //libstdc++
\r
115 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103
\r
117 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_TYPE_TRAITS)
\r
118 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
\r
120 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_CSTDINT)
\r
121 #define HALF_ENABLE_CPP11_CSTDINT 1
\r
123 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_CMATH)
\r
124 #define HALF_ENABLE_CPP11_CMATH 1
\r
126 #if __GLIBCXX__ >= 20080606 && !defined(HALF_ENABLE_CPP11_HASH)
\r
127 #define HALF_ENABLE_CPP11_HASH 1
\r
130 #if HALF_GNUC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_CSTDINT)
\r
131 #define HALF_ENABLE_CPP11_CSTDINT 1
\r
133 #if HALF_GNUC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_CMATH)
\r
134 #define HALF_ENABLE_CPP11_CMATH 1
\r
136 #if HALF_GNUC_VERSION >= 403 && !defined(HALF_ENABLE_CPP11_HASH)
\r
137 #define HALF_ENABLE_CPP11_HASH 1
\r
141 #elif defined(_CPPLIB_VER) //Dinkumware/Visual C++
\r
142 #if _CPPLIB_VER >= 520
\r
143 #ifndef HALF_ENABLE_CPP11_TYPE_TRAITS
\r
144 #define HALF_ENABLE_CPP11_TYPE_TRAITS 1
\r
146 #ifndef HALF_ENABLE_CPP11_CSTDINT
\r
147 #define HALF_ENABLE_CPP11_CSTDINT 1
\r
149 #ifndef HALF_ENABLE_CPP11_HASH
\r
150 #define HALF_ENABLE_CPP11_HASH 1
\r
153 #if _CPPLIB_VER >= 610
\r
154 #ifndef HALF_ENABLE_CPP11_CMATH
\r
155 #define HALF_ENABLE_CPP11_CMATH 1
\r
159 #undef HALF_GNUC_VERSION
\r
161 //support constexpr
\r
162 #if HALF_ENABLE_CPP11_CONSTEXPR
\r
163 #define HALF_CONSTEXPR constexpr
\r
164 #define HALF_CONSTEXPR_CONST constexpr
\r
166 #define HALF_CONSTEXPR
\r
167 #define HALF_CONSTEXPR_CONST const
\r
171 #if HALF_ENABLE_CPP11_NOEXCEPT
\r
172 #define HALF_NOEXCEPT noexcept
\r
173 #define HALF_NOTHROW noexcept
\r
175 #define HALF_NOEXCEPT
\r
176 #define HALF_NOTHROW throw()
\r
179 #include <algorithm>
\r
180 #include <iostream>
\r
186 #if HALF_ENABLE_CPP11_TYPE_TRAITS
\r
187 #include <type_traits>
\r
189 #if HALF_ENABLE_CPP11_CSTDINT
\r
192 #if HALF_ENABLE_CPP11_HASH
\r
193 #include <functional>
\r
197 /// Default rounding mode.
\r
198 /// This specifies the rounding mode used for all conversions between [half](\ref half_float::half)s and `float`s as well as
\r
199 /// for the half_cast() if not specifying a rounding mode explicitly. It can be redefined (before including half.hpp) to one
\r
200 /// of the standard rounding modes using their respective constants or the equivalent values of `std::float_round_style`:
\r
202 /// `std::float_round_style` | value | rounding
\r
203 /// ---------------------------------|-------|-------------------------
\r
204 /// `std::round_indeterminate` | -1 | fastest (default)
\r
205 /// `std::round_toward_zero` | 0 | toward zero
\r
206 /// `std::round_to_nearest` | 1 | to nearest
\r
207 /// `std::round_toward_infinity` | 2 | toward positive infinity
\r
208 /// `std::round_toward_neg_infinity` | 3 | toward negative infinity
\r
210 /// By default this is set to `-1` (`std::round_indeterminate`), which uses truncation (round toward zero, but with overflows
\r
211 /// set to infinity) and is the fastest rounding mode possible. It can even be set to `std::numeric_limits<float>::round_style`
\r
212 /// to synchronize the rounding mode with that of the underlying single-precision implementation.
\r
213 #ifndef HALF_ROUND_STYLE
\r
214 #define HALF_ROUND_STYLE -1 // = std::round_indeterminate
\r
217 /// Tie-breaking behaviour for round to nearest.
\r
218 /// This specifies if ties in round to nearest should be resolved by rounding to the nearest even value. By default this is
\r
219 /// defined to `0` resulting in the faster but slightly more biased behaviour of rounding away from zero in half-way cases (and
\r
220 /// thus equal to the round() function), but can be redefined to `1` (before including half.hpp) if more IEEE-conformant
\r
221 /// behaviour is needed.
\r
222 #ifndef HALF_ROUND_TIES_TO_EVEN
\r
223 #define HALF_ROUND_TIES_TO_EVEN 0 // ties away from zero
\r
226 /// Value signaling overflow.
\r
227 /// In correspondence with `HUGE_VAL[F|L]` from `<cmath>` this symbol expands to a positive value signaling the overflow of an
\r
228 /// operation, in particular it just evaluates to positive infinity.
\r
229 #define HUGE_VALH std::numeric_limits<half_float::half>::infinity()
\r
231 /// Fast half-precision fma function.
\r
232 /// This symbol is only defined if the fma() function generally executes as fast as, or faster than, a separate
\r
233 /// half-precision multiplication followed by an addition. Due to the internal single-precision implementation of all
\r
234 /// arithmetic operations, this is in fact always the case.
\r
235 #define FP_FAST_FMAH 1
\r
238 #define FP_ILOGB0 INT_MIN
\r
240 #ifndef FP_ILOGBNAN
\r
241 #define FP_ILOGBNAN INT_MAX
\r
243 #ifndef FP_SUBNORMAL
\r
244 #define FP_SUBNORMAL 0
\r
252 #ifndef FP_INFINITE
\r
253 #define FP_INFINITE 3
\r
256 #define FP_NORMAL 4
\r
260 /// Main namespace for half precision functionality.
\r
261 /// This namespace contains all the functionality provided by the library.
\r
262 namespace half_float
\r
266 #if HALF_ENABLE_CPP11_USER_LITERALS
\r
267 /// Library-defined half-precision literals.
\r
268 /// Import this namespace to enable half-precision floating point literals:
\r
270 /// using namespace half_float::literal;
\r
271 /// half_float::half = 4.2_h;
\r
275 half operator""_h(long double);
\r
280 /// \brief Implementation details.
\r
283 #if HALF_ENABLE_CPP11_TYPE_TRAITS
\r
284 /// Conditional type.
\r
285 template<bool B,typename T,typename F> struct conditional : std::conditional<B,T,F> {};
\r
287 /// Helper for tag dispatching.
\r
288 template<bool B> struct bool_type : std::integral_constant<bool,B> {};
\r
289 using std::true_type;
\r
290 using std::false_type;
\r
292 /// Type traits for floating point types.
\r
293 template<typename T> struct is_float : std::is_floating_point<T> {};
\r
295 /// Conditional type.
\r
296 template<bool,typename T,typename> struct conditional { typedef T type; };
\r
297 template<typename T,typename F> struct conditional<false,T,F> { typedef F type; };
\r
299 /// Helper for tag dispatching.
\r
300 template<bool> struct bool_type {};
\r
301 typedef bool_type<true> true_type;
\r
302 typedef bool_type<false> false_type;
\r
304 /// Type traits for floating point types.
\r
305 template<typename> struct is_float : false_type {};
\r
306 template<typename T> struct is_float<const T> : is_float<T> {};
\r
307 template<typename T> struct is_float<volatile T> : is_float<T> {};
\r
308 template<typename T> struct is_float<const volatile T> : is_float<T> {};
\r
309 template<> struct is_float<float> : true_type {};
\r
310 template<> struct is_float<double> : true_type {};
\r
311 template<> struct is_float<long double> : true_type {};
\r
314 /// Type traits for floating point bits.
\r
315 template<typename T> struct bits { typedef unsigned char type; };
\r
316 template<typename T> struct bits<const T> : bits<T> {};
\r
317 template<typename T> struct bits<volatile T> : bits<T> {};
\r
318 template<typename T> struct bits<const volatile T> : bits<T> {};
\r
320 #if HALF_ENABLE_CPP11_CSTDINT
\r
321 /// Unsigned integer of (at least) 16 bits width.
\r
322 typedef std::uint_least16_t uint16;
\r
324 /// Unsigned integer of (at least) 32 bits width.
\r
325 template<> struct bits<float> { typedef std::uint_least32_t type; };
\r
327 /// Unsigned integer of (at least) 64 bits width.
\r
328 template<> struct bits<double> { typedef std::uint_least64_t type; };
\r
330 /// Unsigned integer of (at least) 16 bits width.
\r
331 typedef unsigned short uint16;
\r
333 /// Unsigned integer of (at least) 32 bits width.
\r
334 template<> struct bits<float> : conditional<std::numeric_limits<unsigned int>::digits>=32,unsigned int,unsigned long> {};
\r
336 #if HALF_ENABLE_CPP11_LONG_LONG
\r
337 /// Unsigned integer of (at least) 64 bits width.
\r
338 template<> struct bits<double> : conditional<std::numeric_limits<unsigned long>::digits>=64,unsigned long,unsigned long long> {};
\r
340 /// Unsigned integer of (at least) 64 bits width.
\r
341 template<> struct bits<double> { typedef unsigned long type; };
\r
345 /// Tag type for binary construction.
\r
346 struct binary_t {};
\r
348 /// Tag for binary construction.
\r
349 HALF_CONSTEXPR_CONST binary_t binary = binary_t();
\r
351 /// Temporary half-precision expression.
\r
352 /// This class represents a half-precision expression which just stores a single-precision value internally.
\r
355 /// Conversion constructor.
\r
356 /// \param f single-precision value to convert
\r
357 explicit HALF_CONSTEXPR expr(float f) HALF_NOEXCEPT : value_(f) {}
\r
359 /// Conversion to single-precision.
\r
360 /// \return single precision value representing expression value
\r
361 HALF_CONSTEXPR operator float() const HALF_NOEXCEPT { return value_; }
\r
364 /// Internal expression value stored in single-precision.
\r
368 /// SFINAE helper for generic half-precision functions.
\r
369 /// This class template has to be specialized for each valid combination of argument types to provide a corresponding
\r
370 /// `type` member equivalent to \a T.
\r
371 /// \tparam T type to return
\r
372 template<typename T,typename,typename=void,typename=void> struct enable {};
\r
373 template<typename T> struct enable<T,half,void,void> { typedef T type; };
\r
374 template<typename T> struct enable<T,expr,void,void> { typedef T type; };
\r
375 template<typename T> struct enable<T,half,half,void> { typedef T type; };
\r
376 template<typename T> struct enable<T,half,expr,void> { typedef T type; };
\r
377 template<typename T> struct enable<T,expr,half,void> { typedef T type; };
\r
378 template<typename T> struct enable<T,expr,expr,void> { typedef T type; };
\r
379 template<typename T> struct enable<T,half,half,half> { typedef T type; };
\r
380 template<typename T> struct enable<T,half,half,expr> { typedef T type; };
\r
381 template<typename T> struct enable<T,half,expr,half> { typedef T type; };
\r
382 template<typename T> struct enable<T,half,expr,expr> { typedef T type; };
\r
383 template<typename T> struct enable<T,expr,half,half> { typedef T type; };
\r
384 template<typename T> struct enable<T,expr,half,expr> { typedef T type; };
\r
385 template<typename T> struct enable<T,expr,expr,half> { typedef T type; };
\r
386 template<typename T> struct enable<T,expr,expr,expr> { typedef T type; };
\r
388 /// Return type for specialized generic 2-argument half-precision functions.
\r
389 /// This class template has to be specialized for each valid combination of argument types to provide a corresponding
\r
390 /// `type` member denoting the appropriate return type.
\r
391 /// \tparam T first argument type
\r
392 /// \tparam U first argument type
\r
393 template<typename T,typename U> struct result : enable<expr,T,U> {};
\r
394 template<> struct result<half,half> { typedef half type; };
\r
396 /// \name Classification helpers
\r
399 /// Check for infinity.
\r
400 /// \tparam T argument type (builtin floating point type)
\r
401 /// \param arg value to query
\r
402 /// \retval true if infinity
\r
403 /// \retval false else
\r
404 template<typename T> bool builtin_isinf(T arg)
\r
406 #if HALF_ENABLE_CPP11_CMATH
\r
407 return std::isinf(arg);
\r
408 #elif defined(_MSC_VER)
\r
409 return !::_finite(static_cast<double>(arg)) && !::_isnan(static_cast<double>(arg));
\r
411 return arg == std::numeric_limits<T>::infinity() || arg == -std::numeric_limits<T>::infinity();
\r
416 /// \tparam T argument type (builtin floating point type)
\r
417 /// \param arg value to query
\r
418 /// \retval true if not a number
\r
419 /// \retval false else
\r
420 template<typename T> bool builtin_isnan(T arg)
\r
422 #if HALF_ENABLE_CPP11_CMATH
\r
423 return std::isnan(arg);
\r
424 #elif defined(_MSC_VER)
\r
425 return ::_isnan(static_cast<double>(arg)) != 0;
\r
432 /// \tparam T argument type (builtin floating point type)
\r
433 /// \param arg value to query
\r
434 /// \retval true if signbit set
\r
435 /// \retval false else
\r
436 template<typename T> bool builtin_signbit(T arg)
\r
438 #if HALF_ENABLE_CPP11_CMATH
\r
439 return std::signbit(arg);
\r
441 return arg < T() || (arg == T() && T(1)/arg < T());
\r
446 /// \name Conversion
\r
449 /// Convert IEEE single-precision to half-precision.
\r
450 /// Credit for this goes to [Jeroen van der Zijp](ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf).
\r
451 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
452 /// \param value single-precision value
\r
453 /// \return binary representation of half-precision value
\r
454 template<std::float_round_style R> uint16 float2half_impl(float value, true_type)
\r
456 typedef bits<float>::type uint32;
\r
457 uint32 bits;// = *reinterpret_cast<uint32*>(&value); //violating strict aliasing!
\r
458 std::memcpy(&bits, &value, sizeof(float));
\r
459 /* uint16 hbits = (bits>>16) & 0x8000;
\r
460 bits &= 0x7FFFFFFF;
\r
461 int exp = bits >> 23;
\r
463 return hbits | 0x7C00 | (0x3FF&-static_cast<unsigned>((bits&0x7FFFFF)!=0));
\r
466 if(R == std::round_toward_infinity)
\r
467 return hbits | 0x7C00 - (hbits>>15);
\r
468 if(R == std::round_toward_neg_infinity)
\r
469 return hbits | 0x7BFF + (hbits>>15);
\r
470 return hbits | 0x7BFF + (R!=std::round_toward_zero);
\r
475 g = (bits>>12) & 1;
\r
476 s = (bits&0xFFF) != 0;
\r
477 hbits |= ((exp-112)<<10) | ((bits>>13)&0x3FF);
\r
482 bits = (bits&0x7FFFFF) | 0x800000;
\r
484 s = (bits&((1L<<i)-1)) != 0;
\r
485 hbits |= bits >> (i+1);
\r
492 if(R == std::round_to_nearest)
\r
493 #if HALF_ROUND_TIES_TO_EVEN
\r
494 hbits += g & (s|hbits);
\r
498 else if(R == std::round_toward_infinity)
\r
499 hbits += ~(hbits>>15) & (s|g);
\r
500 else if(R == std::round_toward_neg_infinity)
\r
501 hbits += (hbits>>15) & (g|s);
\r
502 */ static const uint16 base_table[512] = {
\r
503 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
504 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
505 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
506 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
507 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
508 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
\r
509 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
\r
510 0x0200, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, 0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00,
\r
511 0x4000, 0x4400, 0x4800, 0x4C00, 0x5000, 0x5400, 0x5800, 0x5C00, 0x6000, 0x6400, 0x6800, 0x6C00, 0x7000, 0x7400, 0x7800, 0x7C00,
\r
512 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
513 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
514 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
515 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
516 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
517 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
518 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00, 0x7C00,
\r
519 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
520 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
521 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
522 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
523 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
524 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
\r
525 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, 0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100,
\r
526 0x8200, 0x8400, 0x8800, 0x8C00, 0x9000, 0x9400, 0x9800, 0x9C00, 0xA000, 0xA400, 0xA800, 0xAC00, 0xB000, 0xB400, 0xB800, 0xBC00,
\r
527 0xC000, 0xC400, 0xC800, 0xCC00, 0xD000, 0xD400, 0xD800, 0xDC00, 0xE000, 0xE400, 0xE800, 0xEC00, 0xF000, 0xF400, 0xF800, 0xFC00,
\r
528 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
529 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
530 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
531 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
532 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
533 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00,
\r
534 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00, 0xFC00 };
\r
535 static const unsigned char shift_table[512] = {
\r
536 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, 24, 24, 24, 24, 24,
\r
537 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, 24, 24, 24, 24, 24,
\r
538 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, 24, 24, 24, 24, 24,
\r
539 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
\r
540 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
\r
541 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, 24, 24, 24, 24, 24,
\r
542 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, 24, 24, 24, 24, 24,
\r
543 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, 24, 24, 24, 24, 13,
\r
544 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, 24, 24, 24, 24, 24,
\r
545 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, 24, 24, 24, 24, 24,
\r
546 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, 24, 24, 24, 24, 24,
\r
547 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
\r
548 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
\r
549 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, 24, 24, 24, 24, 24,
\r
550 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, 24, 24, 24, 24, 24,
\r
551 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, 24, 24, 24, 24, 13 };
\r
552 uint16 hbits = base_table[bits>>23] + static_cast<uint16>((bits&0x7FFFFF)>>shift_table[bits>>23]);
\r
553 if(R == std::round_to_nearest)
\r
554 hbits += (((bits&0x7FFFFF)>>(shift_table[bits>>23]-1))|(((bits>>23)&0xFF)==102)) & ((hbits&0x7C00)!=0x7C00)
\r
555 #if HALF_ROUND_TIES_TO_EVEN
\r
556 & (((((static_cast<uint32>(1)<<(shift_table[bits>>23]-1))-1)&bits)!=0)|hbits)
\r
559 else if(R == std::round_toward_zero)
\r
560 hbits -= ((hbits&0x7FFF)==0x7C00) & ~shift_table[bits>>23];
\r
561 else if(R == std::round_toward_infinity)
\r
562 hbits += ((((bits&0x7FFFFF&((static_cast<uint32>(1)<<(shift_table[bits>>23]))-1))!=0)|(((bits>>23)<=102)&
\r
563 ((bits>>23)!=0)))&(hbits<0x7C00)) - ((hbits==0xFC00)&((bits>>23)!=511));
\r
564 else if(R == std::round_toward_neg_infinity)
\r
565 hbits += ((((bits&0x7FFFFF&((static_cast<uint32>(1)<<(shift_table[bits>>23]))-1))!=0)|(((bits>>23)<=358)&
\r
566 ((bits>>23)!=256)))&(hbits<0xFC00)&(hbits>>15)) - ((hbits==0x7C00)&((bits>>23)!=255));
\r
570 /// Convert IEEE double-precision to half-precision.
\r
571 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
572 /// \param value double-precision value
\r
573 /// \return binary representation of half-precision value
\r
574 template<std::float_round_style R> uint16 float2half_impl(double value, true_type)
\r
576 typedef bits<float>::type uint32;
\r
577 typedef bits<double>::type uint64;
\r
578 uint64 bits;// = *reinterpret_cast<uint64*>(&value); //violating strict aliasing!
\r
579 std::memcpy(&bits, &value, sizeof(double));
\r
580 uint32 hi = bits >> 32, lo = bits & 0xFFFFFFFF;
\r
581 uint16 hbits = (hi>>16) & 0x8000;
\r
583 int exp = hi >> 20;
\r
585 return hbits | 0x7C00 | (0x3FF&-static_cast<unsigned>((bits&0xFFFFFFFFFFFFF)!=0));
\r
588 if(R == std::round_toward_infinity)
\r
589 return hbits | 0x7C00 - (hbits>>15);
\r
590 if(R == std::round_toward_neg_infinity)
\r
591 return hbits | 0x7BFF + (hbits>>15);
\r
592 return hbits | 0x7BFF + (R!=std::round_toward_zero);
\r
594 int g, s = lo != 0;
\r
598 s |= (hi&0x1FF) != 0;
\r
599 hbits |= ((exp-1008)<<10) | ((hi>>10)&0x3FF);
\r
603 int i = 1018 - exp;
\r
604 hi = (hi&0xFFFFF) | 0x100000;
\r
606 s |= (hi&((1L<<i)-1)) != 0;
\r
607 hbits |= hi >> (i+1);
\r
614 if(R == std::round_to_nearest)
\r
615 #if HALF_ROUND_TIES_TO_EVEN
\r
616 hbits += g & (s|hbits);
\r
620 else if(R == std::round_toward_infinity)
\r
621 hbits += ~(hbits>>15) & (s|g);
\r
622 else if(R == std::round_toward_neg_infinity)
\r
623 hbits += (hbits>>15) & (g|s);
\r
627 /// Convert non-IEEE floating point to half-precision.
\r
628 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
629 /// \tparam T source type (builtin floating point type)
\r
630 /// \param value floating point value
\r
631 /// \return binary representation of half-precision value
\r
632 template<std::float_round_style R,typename T> uint16 float2half_impl(T value, ...)
\r
634 uint16 hbits = static_cast<unsigned>(builtin_signbit(value)) << 15;
\r
637 if(builtin_isnan(value))
\r
638 return hbits | 0x7FFF;
\r
639 if(builtin_isinf(value))
\r
640 return hbits | 0x7C00;
\r
642 std::frexp(value, &exp);
\r
645 if(R == std::round_toward_infinity)
\r
646 return hbits | (0x7C00-(hbits>>15));
\r
647 else if(R == std::round_toward_neg_infinity)
\r
648 return hbits | (0x7BFF+(hbits>>15));
\r
649 return hbits | (0x7BFF+(R!=std::round_toward_zero));
\r
652 value = std::ldexp(value, 24);
\r
655 value = std::ldexp(value, 11-exp);
\r
656 hbits |= ((exp+13)<<10);
\r
658 T ival, frac = std::modf(value, &ival);
\r
659 hbits += static_cast<uint16>(std::abs(static_cast<int>(ival)));
\r
660 if(R == std::round_to_nearest)
\r
662 frac = std::abs(frac);
\r
663 #if HALF_ROUND_TIES_TO_EVEN
\r
664 hbits += (frac>T(0.5)) | ((frac==T(0.5))&hbits);
\r
666 hbits += frac >= T(0.5);
\r
669 else if(R == std::round_toward_infinity)
\r
670 hbits += frac > T();
\r
671 else if(R == std::round_toward_neg_infinity)
\r
672 hbits += frac < T();
\r
676 /// Convert floating point to half-precision.
\r
677 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
678 /// \tparam T source type (builtin floating point type)
\r
679 /// \param value floating point value
\r
680 /// \return binary representation of half-precision value
\r
681 template<std::float_round_style R,typename T> uint16 float2half(T value)
\r
683 return float2half_impl<R>(value, bool_type<std::numeric_limits<T>::is_iec559&&sizeof(typename bits<T>::type)==sizeof(T)>());
\r
686 /// Convert integer to half-precision floating point.
\r
687 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
688 /// \tparam S `true` if value negative, `false` else
\r
689 /// \tparam T type to convert (builtin integer type)
\r
690 /// \param value non-negative integral value
\r
691 /// \return binary representation of half-precision value
\r
692 template<std::float_round_style R,bool S,typename T> uint16 int2half_impl(T value)
\r
694 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
\r
695 static_assert(std::is_integral<T>::value, "int to half conversion only supports builtin integer types");
\r
699 uint16 bits = S << 15;
\r
702 if(R == std::round_toward_infinity)
\r
703 bits |= 0x7C00 - S;
\r
704 else if(R == std::round_toward_neg_infinity)
\r
705 bits |= 0x7BFF + S;
\r
707 bits |= 0x7BFF + (R!=std::round_toward_zero);
\r
711 unsigned int m = value, exp = 24;
\r
712 for(; m<0x400; m<<=1,--exp) ;
\r
713 for(; m>0x7FF; m>>=1,++exp) ;
\r
714 bits |= (exp<<10) + m;
\r
717 if(R == std::round_to_nearest)
\r
718 bits += (value>>(exp-25)) & 1
\r
719 #if HALF_ROUND_TIES_TO_EVEN
\r
720 & (((((1<<(exp-25))-1)&value)!=0)|bits)
\r
723 else if(R == std::round_toward_infinity)
\r
724 bits += ((value&((1<<(exp-24))-1))!=0) & !S;
\r
725 else if(R == std::round_toward_neg_infinity)
\r
726 bits += ((value&((1<<(exp-24))-1))!=0) & S;
\r
732 /// Convert integer to half-precision floating point.
\r
733 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
734 /// \tparam T type to convert (builtin integer type)
\r
735 /// \param value integral value
\r
736 /// \return binary representation of half-precision value
\r
737 template<std::float_round_style R,typename T> uint16 int2half(T value)
\r
739 return (value<0) ? int2half_impl<R,true>(value) : int2half_impl<R,false>(value);
\r
742 /// Convert half-precision to IEEE single-precision.
\r
743 /// Credit for this goes to [Jeroen van der Zijp](ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf).
\r
744 /// \param value binary representation of half-precision value
\r
745 /// \return single-precision value
\r
746 inline float half2float_impl(uint16 value, float, true_type)
\r
748 typedef bits<float>::type uint32;
\r
749 /* uint32 bits = static_cast<uint32>(value&0x8000) << 16;
\r
750 int abs = value & 0x7FFF;
\r
753 bits |= 0x38000000 << static_cast<unsigned>(abs>=0x7C00);
\r
754 for(; abs<0x400; abs<<=1,bits-=0x800000) ;
\r
755 bits += static_cast<uint32>(abs) << 13;
\r
757 */ static const uint32 mantissa_table[2048] = {
\r
758 0x00000000, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34A00000, 0x34C00000, 0x34E00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000, 0x35400000, 0x35500000, 0x35600000, 0x35700000,
\r
759 0x35800000, 0x35880000, 0x35900000, 0x35980000, 0x35A00000, 0x35A80000, 0x35B00000, 0x35B80000, 0x35C00000, 0x35C80000, 0x35D00000, 0x35D80000, 0x35E00000, 0x35E80000, 0x35F00000, 0x35F80000,
\r
760 0x36000000, 0x36040000, 0x36080000, 0x360C0000, 0x36100000, 0x36140000, 0x36180000, 0x361C0000, 0x36200000, 0x36240000, 0x36280000, 0x362C0000, 0x36300000, 0x36340000, 0x36380000, 0x363C0000,
\r
761 0x36400000, 0x36440000, 0x36480000, 0x364C0000, 0x36500000, 0x36540000, 0x36580000, 0x365C0000, 0x36600000, 0x36640000, 0x36680000, 0x366C0000, 0x36700000, 0x36740000, 0x36780000, 0x367C0000,
\r
762 0x36800000, 0x36820000, 0x36840000, 0x36860000, 0x36880000, 0x368A0000, 0x368C0000, 0x368E0000, 0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369A0000, 0x369C0000, 0x369E0000,
\r
763 0x36A00000, 0x36A20000, 0x36A40000, 0x36A60000, 0x36A80000, 0x36AA0000, 0x36AC0000, 0x36AE0000, 0x36B00000, 0x36B20000, 0x36B40000, 0x36B60000, 0x36B80000, 0x36BA0000, 0x36BC0000, 0x36BE0000,
\r
764 0x36C00000, 0x36C20000, 0x36C40000, 0x36C60000, 0x36C80000, 0x36CA0000, 0x36CC0000, 0x36CE0000, 0x36D00000, 0x36D20000, 0x36D40000, 0x36D60000, 0x36D80000, 0x36DA0000, 0x36DC0000, 0x36DE0000,
\r
765 0x36E00000, 0x36E20000, 0x36E40000, 0x36E60000, 0x36E80000, 0x36EA0000, 0x36EC0000, 0x36EE0000, 0x36F00000, 0x36F20000, 0x36F40000, 0x36F60000, 0x36F80000, 0x36FA0000, 0x36FC0000, 0x36FE0000,
\r
766 0x37000000, 0x37010000, 0x37020000, 0x37030000, 0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000, 0x370A0000, 0x370B0000, 0x370C0000, 0x370D0000, 0x370E0000, 0x370F0000,
\r
767 0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000, 0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371A0000, 0x371B0000, 0x371C0000, 0x371D0000, 0x371E0000, 0x371F0000,
\r
768 0x37200000, 0x37210000, 0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000, 0x37280000, 0x37290000, 0x372A0000, 0x372B0000, 0x372C0000, 0x372D0000, 0x372E0000, 0x372F0000,
\r
769 0x37300000, 0x37310000, 0x37320000, 0x37330000, 0x37340000, 0x37350000, 0x37360000, 0x37370000, 0x37380000, 0x37390000, 0x373A0000, 0x373B0000, 0x373C0000, 0x373D0000, 0x373E0000, 0x373F0000,
\r
770 0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, 0x37460000, 0x37470000, 0x37480000, 0x37490000, 0x374A0000, 0x374B0000, 0x374C0000, 0x374D0000, 0x374E0000, 0x374F0000,
\r
771 0x37500000, 0x37510000, 0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000, 0x37580000, 0x37590000, 0x375A0000, 0x375B0000, 0x375C0000, 0x375D0000, 0x375E0000, 0x375F0000,
\r
772 0x37600000, 0x37610000, 0x37620000, 0x37630000, 0x37640000, 0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000, 0x376A0000, 0x376B0000, 0x376C0000, 0x376D0000, 0x376E0000, 0x376F0000,
\r
773 0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, 0x37760000, 0x37770000, 0x37780000, 0x37790000, 0x377A0000, 0x377B0000, 0x377C0000, 0x377D0000, 0x377E0000, 0x377F0000,
\r
774 0x37800000, 0x37808000, 0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000, 0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, 0x37870000, 0x37878000,
\r
775 0x37880000, 0x37888000, 0x37890000, 0x37898000, 0x378A0000, 0x378A8000, 0x378B0000, 0x378B8000, 0x378C0000, 0x378C8000, 0x378D0000, 0x378D8000, 0x378E0000, 0x378E8000, 0x378F0000, 0x378F8000,
\r
776 0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000, 0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000, 0x37960000, 0x37968000, 0x37970000, 0x37978000,
\r
777 0x37980000, 0x37988000, 0x37990000, 0x37998000, 0x379A0000, 0x379A8000, 0x379B0000, 0x379B8000, 0x379C0000, 0x379C8000, 0x379D0000, 0x379D8000, 0x379E0000, 0x379E8000, 0x379F0000, 0x379F8000,
\r
778 0x37A00000, 0x37A08000, 0x37A10000, 0x37A18000, 0x37A20000, 0x37A28000, 0x37A30000, 0x37A38000, 0x37A40000, 0x37A48000, 0x37A50000, 0x37A58000, 0x37A60000, 0x37A68000, 0x37A70000, 0x37A78000,
\r
779 0x37A80000, 0x37A88000, 0x37A90000, 0x37A98000, 0x37AA0000, 0x37AA8000, 0x37AB0000, 0x37AB8000, 0x37AC0000, 0x37AC8000, 0x37AD0000, 0x37AD8000, 0x37AE0000, 0x37AE8000, 0x37AF0000, 0x37AF8000,
\r
780 0x37B00000, 0x37B08000, 0x37B10000, 0x37B18000, 0x37B20000, 0x37B28000, 0x37B30000, 0x37B38000, 0x37B40000, 0x37B48000, 0x37B50000, 0x37B58000, 0x37B60000, 0x37B68000, 0x37B70000, 0x37B78000,
\r
781 0x37B80000, 0x37B88000, 0x37B90000, 0x37B98000, 0x37BA0000, 0x37BA8000, 0x37BB0000, 0x37BB8000, 0x37BC0000, 0x37BC8000, 0x37BD0000, 0x37BD8000, 0x37BE0000, 0x37BE8000, 0x37BF0000, 0x37BF8000,
\r
782 0x37C00000, 0x37C08000, 0x37C10000, 0x37C18000, 0x37C20000, 0x37C28000, 0x37C30000, 0x37C38000, 0x37C40000, 0x37C48000, 0x37C50000, 0x37C58000, 0x37C60000, 0x37C68000, 0x37C70000, 0x37C78000,
\r
783 0x37C80000, 0x37C88000, 0x37C90000, 0x37C98000, 0x37CA0000, 0x37CA8000, 0x37CB0000, 0x37CB8000, 0x37CC0000, 0x37CC8000, 0x37CD0000, 0x37CD8000, 0x37CE0000, 0x37CE8000, 0x37CF0000, 0x37CF8000,
\r
784 0x37D00000, 0x37D08000, 0x37D10000, 0x37D18000, 0x37D20000, 0x37D28000, 0x37D30000, 0x37D38000, 0x37D40000, 0x37D48000, 0x37D50000, 0x37D58000, 0x37D60000, 0x37D68000, 0x37D70000, 0x37D78000,
\r
785 0x37D80000, 0x37D88000, 0x37D90000, 0x37D98000, 0x37DA0000, 0x37DA8000, 0x37DB0000, 0x37DB8000, 0x37DC0000, 0x37DC8000, 0x37DD0000, 0x37DD8000, 0x37DE0000, 0x37DE8000, 0x37DF0000, 0x37DF8000,
\r
786 0x37E00000, 0x37E08000, 0x37E10000, 0x37E18000, 0x37E20000, 0x37E28000, 0x37E30000, 0x37E38000, 0x37E40000, 0x37E48000, 0x37E50000, 0x37E58000, 0x37E60000, 0x37E68000, 0x37E70000, 0x37E78000,
\r
787 0x37E80000, 0x37E88000, 0x37E90000, 0x37E98000, 0x37EA0000, 0x37EA8000, 0x37EB0000, 0x37EB8000, 0x37EC0000, 0x37EC8000, 0x37ED0000, 0x37ED8000, 0x37EE0000, 0x37EE8000, 0x37EF0000, 0x37EF8000,
\r
788 0x37F00000, 0x37F08000, 0x37F10000, 0x37F18000, 0x37F20000, 0x37F28000, 0x37F30000, 0x37F38000, 0x37F40000, 0x37F48000, 0x37F50000, 0x37F58000, 0x37F60000, 0x37F68000, 0x37F70000, 0x37F78000,
\r
789 0x37F80000, 0x37F88000, 0x37F90000, 0x37F98000, 0x37FA0000, 0x37FA8000, 0x37FB0000, 0x37FB8000, 0x37FC0000, 0x37FC8000, 0x37FD0000, 0x37FD8000, 0x37FE0000, 0x37FE8000, 0x37FF0000, 0x37FF8000,
\r
790 0x38000000, 0x38004000, 0x38008000, 0x3800C000, 0x38010000, 0x38014000, 0x38018000, 0x3801C000, 0x38020000, 0x38024000, 0x38028000, 0x3802C000, 0x38030000, 0x38034000, 0x38038000, 0x3803C000,
\r
791 0x38040000, 0x38044000, 0x38048000, 0x3804C000, 0x38050000, 0x38054000, 0x38058000, 0x3805C000, 0x38060000, 0x38064000, 0x38068000, 0x3806C000, 0x38070000, 0x38074000, 0x38078000, 0x3807C000,
\r
792 0x38080000, 0x38084000, 0x38088000, 0x3808C000, 0x38090000, 0x38094000, 0x38098000, 0x3809C000, 0x380A0000, 0x380A4000, 0x380A8000, 0x380AC000, 0x380B0000, 0x380B4000, 0x380B8000, 0x380BC000,
\r
793 0x380C0000, 0x380C4000, 0x380C8000, 0x380CC000, 0x380D0000, 0x380D4000, 0x380D8000, 0x380DC000, 0x380E0000, 0x380E4000, 0x380E8000, 0x380EC000, 0x380F0000, 0x380F4000, 0x380F8000, 0x380FC000,
\r
794 0x38100000, 0x38104000, 0x38108000, 0x3810C000, 0x38110000, 0x38114000, 0x38118000, 0x3811C000, 0x38120000, 0x38124000, 0x38128000, 0x3812C000, 0x38130000, 0x38134000, 0x38138000, 0x3813C000,
\r
795 0x38140000, 0x38144000, 0x38148000, 0x3814C000, 0x38150000, 0x38154000, 0x38158000, 0x3815C000, 0x38160000, 0x38164000, 0x38168000, 0x3816C000, 0x38170000, 0x38174000, 0x38178000, 0x3817C000,
\r
796 0x38180000, 0x38184000, 0x38188000, 0x3818C000, 0x38190000, 0x38194000, 0x38198000, 0x3819C000, 0x381A0000, 0x381A4000, 0x381A8000, 0x381AC000, 0x381B0000, 0x381B4000, 0x381B8000, 0x381BC000,
\r
797 0x381C0000, 0x381C4000, 0x381C8000, 0x381CC000, 0x381D0000, 0x381D4000, 0x381D8000, 0x381DC000, 0x381E0000, 0x381E4000, 0x381E8000, 0x381EC000, 0x381F0000, 0x381F4000, 0x381F8000, 0x381FC000,
\r
798 0x38200000, 0x38204000, 0x38208000, 0x3820C000, 0x38210000, 0x38214000, 0x38218000, 0x3821C000, 0x38220000, 0x38224000, 0x38228000, 0x3822C000, 0x38230000, 0x38234000, 0x38238000, 0x3823C000,
\r
799 0x38240000, 0x38244000, 0x38248000, 0x3824C000, 0x38250000, 0x38254000, 0x38258000, 0x3825C000, 0x38260000, 0x38264000, 0x38268000, 0x3826C000, 0x38270000, 0x38274000, 0x38278000, 0x3827C000,
\r
800 0x38280000, 0x38284000, 0x38288000, 0x3828C000, 0x38290000, 0x38294000, 0x38298000, 0x3829C000, 0x382A0000, 0x382A4000, 0x382A8000, 0x382AC000, 0x382B0000, 0x382B4000, 0x382B8000, 0x382BC000,
\r
801 0x382C0000, 0x382C4000, 0x382C8000, 0x382CC000, 0x382D0000, 0x382D4000, 0x382D8000, 0x382DC000, 0x382E0000, 0x382E4000, 0x382E8000, 0x382EC000, 0x382F0000, 0x382F4000, 0x382F8000, 0x382FC000,
\r
802 0x38300000, 0x38304000, 0x38308000, 0x3830C000, 0x38310000, 0x38314000, 0x38318000, 0x3831C000, 0x38320000, 0x38324000, 0x38328000, 0x3832C000, 0x38330000, 0x38334000, 0x38338000, 0x3833C000,
\r
803 0x38340000, 0x38344000, 0x38348000, 0x3834C000, 0x38350000, 0x38354000, 0x38358000, 0x3835C000, 0x38360000, 0x38364000, 0x38368000, 0x3836C000, 0x38370000, 0x38374000, 0x38378000, 0x3837C000,
\r
804 0x38380000, 0x38384000, 0x38388000, 0x3838C000, 0x38390000, 0x38394000, 0x38398000, 0x3839C000, 0x383A0000, 0x383A4000, 0x383A8000, 0x383AC000, 0x383B0000, 0x383B4000, 0x383B8000, 0x383BC000,
\r
805 0x383C0000, 0x383C4000, 0x383C8000, 0x383CC000, 0x383D0000, 0x383D4000, 0x383D8000, 0x383DC000, 0x383E0000, 0x383E4000, 0x383E8000, 0x383EC000, 0x383F0000, 0x383F4000, 0x383F8000, 0x383FC000,
\r
806 0x38400000, 0x38404000, 0x38408000, 0x3840C000, 0x38410000, 0x38414000, 0x38418000, 0x3841C000, 0x38420000, 0x38424000, 0x38428000, 0x3842C000, 0x38430000, 0x38434000, 0x38438000, 0x3843C000,
\r
807 0x38440000, 0x38444000, 0x38448000, 0x3844C000, 0x38450000, 0x38454000, 0x38458000, 0x3845C000, 0x38460000, 0x38464000, 0x38468000, 0x3846C000, 0x38470000, 0x38474000, 0x38478000, 0x3847C000,
\r
808 0x38480000, 0x38484000, 0x38488000, 0x3848C000, 0x38490000, 0x38494000, 0x38498000, 0x3849C000, 0x384A0000, 0x384A4000, 0x384A8000, 0x384AC000, 0x384B0000, 0x384B4000, 0x384B8000, 0x384BC000,
\r
809 0x384C0000, 0x384C4000, 0x384C8000, 0x384CC000, 0x384D0000, 0x384D4000, 0x384D8000, 0x384DC000, 0x384E0000, 0x384E4000, 0x384E8000, 0x384EC000, 0x384F0000, 0x384F4000, 0x384F8000, 0x384FC000,
\r
810 0x38500000, 0x38504000, 0x38508000, 0x3850C000, 0x38510000, 0x38514000, 0x38518000, 0x3851C000, 0x38520000, 0x38524000, 0x38528000, 0x3852C000, 0x38530000, 0x38534000, 0x38538000, 0x3853C000,
\r
811 0x38540000, 0x38544000, 0x38548000, 0x3854C000, 0x38550000, 0x38554000, 0x38558000, 0x3855C000, 0x38560000, 0x38564000, 0x38568000, 0x3856C000, 0x38570000, 0x38574000, 0x38578000, 0x3857C000,
\r
812 0x38580000, 0x38584000, 0x38588000, 0x3858C000, 0x38590000, 0x38594000, 0x38598000, 0x3859C000, 0x385A0000, 0x385A4000, 0x385A8000, 0x385AC000, 0x385B0000, 0x385B4000, 0x385B8000, 0x385BC000,
\r
813 0x385C0000, 0x385C4000, 0x385C8000, 0x385CC000, 0x385D0000, 0x385D4000, 0x385D8000, 0x385DC000, 0x385E0000, 0x385E4000, 0x385E8000, 0x385EC000, 0x385F0000, 0x385F4000, 0x385F8000, 0x385FC000,
\r
814 0x38600000, 0x38604000, 0x38608000, 0x3860C000, 0x38610000, 0x38614000, 0x38618000, 0x3861C000, 0x38620000, 0x38624000, 0x38628000, 0x3862C000, 0x38630000, 0x38634000, 0x38638000, 0x3863C000,
\r
815 0x38640000, 0x38644000, 0x38648000, 0x3864C000, 0x38650000, 0x38654000, 0x38658000, 0x3865C000, 0x38660000, 0x38664000, 0x38668000, 0x3866C000, 0x38670000, 0x38674000, 0x38678000, 0x3867C000,
\r
816 0x38680000, 0x38684000, 0x38688000, 0x3868C000, 0x38690000, 0x38694000, 0x38698000, 0x3869C000, 0x386A0000, 0x386A4000, 0x386A8000, 0x386AC000, 0x386B0000, 0x386B4000, 0x386B8000, 0x386BC000,
\r
817 0x386C0000, 0x386C4000, 0x386C8000, 0x386CC000, 0x386D0000, 0x386D4000, 0x386D8000, 0x386DC000, 0x386E0000, 0x386E4000, 0x386E8000, 0x386EC000, 0x386F0000, 0x386F4000, 0x386F8000, 0x386FC000,
\r
818 0x38700000, 0x38704000, 0x38708000, 0x3870C000, 0x38710000, 0x38714000, 0x38718000, 0x3871C000, 0x38720000, 0x38724000, 0x38728000, 0x3872C000, 0x38730000, 0x38734000, 0x38738000, 0x3873C000,
\r
819 0x38740000, 0x38744000, 0x38748000, 0x3874C000, 0x38750000, 0x38754000, 0x38758000, 0x3875C000, 0x38760000, 0x38764000, 0x38768000, 0x3876C000, 0x38770000, 0x38774000, 0x38778000, 0x3877C000,
\r
820 0x38780000, 0x38784000, 0x38788000, 0x3878C000, 0x38790000, 0x38794000, 0x38798000, 0x3879C000, 0x387A0000, 0x387A4000, 0x387A8000, 0x387AC000, 0x387B0000, 0x387B4000, 0x387B8000, 0x387BC000,
\r
821 0x387C0000, 0x387C4000, 0x387C8000, 0x387CC000, 0x387D0000, 0x387D4000, 0x387D8000, 0x387DC000, 0x387E0000, 0x387E4000, 0x387E8000, 0x387EC000, 0x387F0000, 0x387F4000, 0x387F8000, 0x387FC000,
\r
822 0x38000000, 0x38002000, 0x38004000, 0x38006000, 0x38008000, 0x3800A000, 0x3800C000, 0x3800E000, 0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801A000, 0x3801C000, 0x3801E000,
\r
823 0x38020000, 0x38022000, 0x38024000, 0x38026000, 0x38028000, 0x3802A000, 0x3802C000, 0x3802E000, 0x38030000, 0x38032000, 0x38034000, 0x38036000, 0x38038000, 0x3803A000, 0x3803C000, 0x3803E000,
\r
824 0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804A000, 0x3804C000, 0x3804E000, 0x38050000, 0x38052000, 0x38054000, 0x38056000, 0x38058000, 0x3805A000, 0x3805C000, 0x3805E000,
\r
825 0x38060000, 0x38062000, 0x38064000, 0x38066000, 0x38068000, 0x3806A000, 0x3806C000, 0x3806E000, 0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807A000, 0x3807C000, 0x3807E000,
\r
826 0x38080000, 0x38082000, 0x38084000, 0x38086000, 0x38088000, 0x3808A000, 0x3808C000, 0x3808E000, 0x38090000, 0x38092000, 0x38094000, 0x38096000, 0x38098000, 0x3809A000, 0x3809C000, 0x3809E000,
\r
827 0x380A0000, 0x380A2000, 0x380A4000, 0x380A6000, 0x380A8000, 0x380AA000, 0x380AC000, 0x380AE000, 0x380B0000, 0x380B2000, 0x380B4000, 0x380B6000, 0x380B8000, 0x380BA000, 0x380BC000, 0x380BE000,
\r
828 0x380C0000, 0x380C2000, 0x380C4000, 0x380C6000, 0x380C8000, 0x380CA000, 0x380CC000, 0x380CE000, 0x380D0000, 0x380D2000, 0x380D4000, 0x380D6000, 0x380D8000, 0x380DA000, 0x380DC000, 0x380DE000,
\r
829 0x380E0000, 0x380E2000, 0x380E4000, 0x380E6000, 0x380E8000, 0x380EA000, 0x380EC000, 0x380EE000, 0x380F0000, 0x380F2000, 0x380F4000, 0x380F6000, 0x380F8000, 0x380FA000, 0x380FC000, 0x380FE000,
\r
830 0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810A000, 0x3810C000, 0x3810E000, 0x38110000, 0x38112000, 0x38114000, 0x38116000, 0x38118000, 0x3811A000, 0x3811C000, 0x3811E000,
\r
831 0x38120000, 0x38122000, 0x38124000, 0x38126000, 0x38128000, 0x3812A000, 0x3812C000, 0x3812E000, 0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813A000, 0x3813C000, 0x3813E000,
\r
832 0x38140000, 0x38142000, 0x38144000, 0x38146000, 0x38148000, 0x3814A000, 0x3814C000, 0x3814E000, 0x38150000, 0x38152000, 0x38154000, 0x38156000, 0x38158000, 0x3815A000, 0x3815C000, 0x3815E000,
\r
833 0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816A000, 0x3816C000, 0x3816E000, 0x38170000, 0x38172000, 0x38174000, 0x38176000, 0x38178000, 0x3817A000, 0x3817C000, 0x3817E000,
\r
834 0x38180000, 0x38182000, 0x38184000, 0x38186000, 0x38188000, 0x3818A000, 0x3818C000, 0x3818E000, 0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819A000, 0x3819C000, 0x3819E000,
\r
835 0x381A0000, 0x381A2000, 0x381A4000, 0x381A6000, 0x381A8000, 0x381AA000, 0x381AC000, 0x381AE000, 0x381B0000, 0x381B2000, 0x381B4000, 0x381B6000, 0x381B8000, 0x381BA000, 0x381BC000, 0x381BE000,
\r
836 0x381C0000, 0x381C2000, 0x381C4000, 0x381C6000, 0x381C8000, 0x381CA000, 0x381CC000, 0x381CE000, 0x381D0000, 0x381D2000, 0x381D4000, 0x381D6000, 0x381D8000, 0x381DA000, 0x381DC000, 0x381DE000,
\r
837 0x381E0000, 0x381E2000, 0x381E4000, 0x381E6000, 0x381E8000, 0x381EA000, 0x381EC000, 0x381EE000, 0x381F0000, 0x381F2000, 0x381F4000, 0x381F6000, 0x381F8000, 0x381FA000, 0x381FC000, 0x381FE000,
\r
838 0x38200000, 0x38202000, 0x38204000, 0x38206000, 0x38208000, 0x3820A000, 0x3820C000, 0x3820E000, 0x38210000, 0x38212000, 0x38214000, 0x38216000, 0x38218000, 0x3821A000, 0x3821C000, 0x3821E000,
\r
839 0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822A000, 0x3822C000, 0x3822E000, 0x38230000, 0x38232000, 0x38234000, 0x38236000, 0x38238000, 0x3823A000, 0x3823C000, 0x3823E000,
\r
840 0x38240000, 0x38242000, 0x38244000, 0x38246000, 0x38248000, 0x3824A000, 0x3824C000, 0x3824E000, 0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825A000, 0x3825C000, 0x3825E000,
\r
841 0x38260000, 0x38262000, 0x38264000, 0x38266000, 0x38268000, 0x3826A000, 0x3826C000, 0x3826E000, 0x38270000, 0x38272000, 0x38274000, 0x38276000, 0x38278000, 0x3827A000, 0x3827C000, 0x3827E000,
\r
842 0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828A000, 0x3828C000, 0x3828E000, 0x38290000, 0x38292000, 0x38294000, 0x38296000, 0x38298000, 0x3829A000, 0x3829C000, 0x3829E000,
\r
843 0x382A0000, 0x382A2000, 0x382A4000, 0x382A6000, 0x382A8000, 0x382AA000, 0x382AC000, 0x382AE000, 0x382B0000, 0x382B2000, 0x382B4000, 0x382B6000, 0x382B8000, 0x382BA000, 0x382BC000, 0x382BE000,
\r
844 0x382C0000, 0x382C2000, 0x382C4000, 0x382C6000, 0x382C8000, 0x382CA000, 0x382CC000, 0x382CE000, 0x382D0000, 0x382D2000, 0x382D4000, 0x382D6000, 0x382D8000, 0x382DA000, 0x382DC000, 0x382DE000,
\r
845 0x382E0000, 0x382E2000, 0x382E4000, 0x382E6000, 0x382E8000, 0x382EA000, 0x382EC000, 0x382EE000, 0x382F0000, 0x382F2000, 0x382F4000, 0x382F6000, 0x382F8000, 0x382FA000, 0x382FC000, 0x382FE000,
\r
846 0x38300000, 0x38302000, 0x38304000, 0x38306000, 0x38308000, 0x3830A000, 0x3830C000, 0x3830E000, 0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831A000, 0x3831C000, 0x3831E000,
\r
847 0x38320000, 0x38322000, 0x38324000, 0x38326000, 0x38328000, 0x3832A000, 0x3832C000, 0x3832E000, 0x38330000, 0x38332000, 0x38334000, 0x38336000, 0x38338000, 0x3833A000, 0x3833C000, 0x3833E000,
\r
848 0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834A000, 0x3834C000, 0x3834E000, 0x38350000, 0x38352000, 0x38354000, 0x38356000, 0x38358000, 0x3835A000, 0x3835C000, 0x3835E000,
\r
849 0x38360000, 0x38362000, 0x38364000, 0x38366000, 0x38368000, 0x3836A000, 0x3836C000, 0x3836E000, 0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837A000, 0x3837C000, 0x3837E000,
\r
850 0x38380000, 0x38382000, 0x38384000, 0x38386000, 0x38388000, 0x3838A000, 0x3838C000, 0x3838E000, 0x38390000, 0x38392000, 0x38394000, 0x38396000, 0x38398000, 0x3839A000, 0x3839C000, 0x3839E000,
\r
851 0x383A0000, 0x383A2000, 0x383A4000, 0x383A6000, 0x383A8000, 0x383AA000, 0x383AC000, 0x383AE000, 0x383B0000, 0x383B2000, 0x383B4000, 0x383B6000, 0x383B8000, 0x383BA000, 0x383BC000, 0x383BE000,
\r
852 0x383C0000, 0x383C2000, 0x383C4000, 0x383C6000, 0x383C8000, 0x383CA000, 0x383CC000, 0x383CE000, 0x383D0000, 0x383D2000, 0x383D4000, 0x383D6000, 0x383D8000, 0x383DA000, 0x383DC000, 0x383DE000,
\r
853 0x383E0000, 0x383E2000, 0x383E4000, 0x383E6000, 0x383E8000, 0x383EA000, 0x383EC000, 0x383EE000, 0x383F0000, 0x383F2000, 0x383F4000, 0x383F6000, 0x383F8000, 0x383FA000, 0x383FC000, 0x383FE000,
\r
854 0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840A000, 0x3840C000, 0x3840E000, 0x38410000, 0x38412000, 0x38414000, 0x38416000, 0x38418000, 0x3841A000, 0x3841C000, 0x3841E000,
\r
855 0x38420000, 0x38422000, 0x38424000, 0x38426000, 0x38428000, 0x3842A000, 0x3842C000, 0x3842E000, 0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843A000, 0x3843C000, 0x3843E000,
\r
856 0x38440000, 0x38442000, 0x38444000, 0x38446000, 0x38448000, 0x3844A000, 0x3844C000, 0x3844E000, 0x38450000, 0x38452000, 0x38454000, 0x38456000, 0x38458000, 0x3845A000, 0x3845C000, 0x3845E000,
\r
857 0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846A000, 0x3846C000, 0x3846E000, 0x38470000, 0x38472000, 0x38474000, 0x38476000, 0x38478000, 0x3847A000, 0x3847C000, 0x3847E000,
\r
858 0x38480000, 0x38482000, 0x38484000, 0x38486000, 0x38488000, 0x3848A000, 0x3848C000, 0x3848E000, 0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849A000, 0x3849C000, 0x3849E000,
\r
859 0x384A0000, 0x384A2000, 0x384A4000, 0x384A6000, 0x384A8000, 0x384AA000, 0x384AC000, 0x384AE000, 0x384B0000, 0x384B2000, 0x384B4000, 0x384B6000, 0x384B8000, 0x384BA000, 0x384BC000, 0x384BE000,
\r
860 0x384C0000, 0x384C2000, 0x384C4000, 0x384C6000, 0x384C8000, 0x384CA000, 0x384CC000, 0x384CE000, 0x384D0000, 0x384D2000, 0x384D4000, 0x384D6000, 0x384D8000, 0x384DA000, 0x384DC000, 0x384DE000,
\r
861 0x384E0000, 0x384E2000, 0x384E4000, 0x384E6000, 0x384E8000, 0x384EA000, 0x384EC000, 0x384EE000, 0x384F0000, 0x384F2000, 0x384F4000, 0x384F6000, 0x384F8000, 0x384FA000, 0x384FC000, 0x384FE000,
\r
862 0x38500000, 0x38502000, 0x38504000, 0x38506000, 0x38508000, 0x3850A000, 0x3850C000, 0x3850E000, 0x38510000, 0x38512000, 0x38514000, 0x38516000, 0x38518000, 0x3851A000, 0x3851C000, 0x3851E000,
\r
863 0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852A000, 0x3852C000, 0x3852E000, 0x38530000, 0x38532000, 0x38534000, 0x38536000, 0x38538000, 0x3853A000, 0x3853C000, 0x3853E000,
\r
864 0x38540000, 0x38542000, 0x38544000, 0x38546000, 0x38548000, 0x3854A000, 0x3854C000, 0x3854E000, 0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855A000, 0x3855C000, 0x3855E000,
\r
865 0x38560000, 0x38562000, 0x38564000, 0x38566000, 0x38568000, 0x3856A000, 0x3856C000, 0x3856E000, 0x38570000, 0x38572000, 0x38574000, 0x38576000, 0x38578000, 0x3857A000, 0x3857C000, 0x3857E000,
\r
866 0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858A000, 0x3858C000, 0x3858E000, 0x38590000, 0x38592000, 0x38594000, 0x38596000, 0x38598000, 0x3859A000, 0x3859C000, 0x3859E000,
\r
867 0x385A0000, 0x385A2000, 0x385A4000, 0x385A6000, 0x385A8000, 0x385AA000, 0x385AC000, 0x385AE000, 0x385B0000, 0x385B2000, 0x385B4000, 0x385B6000, 0x385B8000, 0x385BA000, 0x385BC000, 0x385BE000,
\r
868 0x385C0000, 0x385C2000, 0x385C4000, 0x385C6000, 0x385C8000, 0x385CA000, 0x385CC000, 0x385CE000, 0x385D0000, 0x385D2000, 0x385D4000, 0x385D6000, 0x385D8000, 0x385DA000, 0x385DC000, 0x385DE000,
\r
869 0x385E0000, 0x385E2000, 0x385E4000, 0x385E6000, 0x385E8000, 0x385EA000, 0x385EC000, 0x385EE000, 0x385F0000, 0x385F2000, 0x385F4000, 0x385F6000, 0x385F8000, 0x385FA000, 0x385FC000, 0x385FE000,
\r
870 0x38600000, 0x38602000, 0x38604000, 0x38606000, 0x38608000, 0x3860A000, 0x3860C000, 0x3860E000, 0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861A000, 0x3861C000, 0x3861E000,
\r
871 0x38620000, 0x38622000, 0x38624000, 0x38626000, 0x38628000, 0x3862A000, 0x3862C000, 0x3862E000, 0x38630000, 0x38632000, 0x38634000, 0x38636000, 0x38638000, 0x3863A000, 0x3863C000, 0x3863E000,
\r
872 0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864A000, 0x3864C000, 0x3864E000, 0x38650000, 0x38652000, 0x38654000, 0x38656000, 0x38658000, 0x3865A000, 0x3865C000, 0x3865E000,
\r
873 0x38660000, 0x38662000, 0x38664000, 0x38666000, 0x38668000, 0x3866A000, 0x3866C000, 0x3866E000, 0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867A000, 0x3867C000, 0x3867E000,
\r
874 0x38680000, 0x38682000, 0x38684000, 0x38686000, 0x38688000, 0x3868A000, 0x3868C000, 0x3868E000, 0x38690000, 0x38692000, 0x38694000, 0x38696000, 0x38698000, 0x3869A000, 0x3869C000, 0x3869E000,
\r
875 0x386A0000, 0x386A2000, 0x386A4000, 0x386A6000, 0x386A8000, 0x386AA000, 0x386AC000, 0x386AE000, 0x386B0000, 0x386B2000, 0x386B4000, 0x386B6000, 0x386B8000, 0x386BA000, 0x386BC000, 0x386BE000,
\r
876 0x386C0000, 0x386C2000, 0x386C4000, 0x386C6000, 0x386C8000, 0x386CA000, 0x386CC000, 0x386CE000, 0x386D0000, 0x386D2000, 0x386D4000, 0x386D6000, 0x386D8000, 0x386DA000, 0x386DC000, 0x386DE000,
\r
877 0x386E0000, 0x386E2000, 0x386E4000, 0x386E6000, 0x386E8000, 0x386EA000, 0x386EC000, 0x386EE000, 0x386F0000, 0x386F2000, 0x386F4000, 0x386F6000, 0x386F8000, 0x386FA000, 0x386FC000, 0x386FE000,
\r
878 0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870A000, 0x3870C000, 0x3870E000, 0x38710000, 0x38712000, 0x38714000, 0x38716000, 0x38718000, 0x3871A000, 0x3871C000, 0x3871E000,
\r
879 0x38720000, 0x38722000, 0x38724000, 0x38726000, 0x38728000, 0x3872A000, 0x3872C000, 0x3872E000, 0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873A000, 0x3873C000, 0x3873E000,
\r
880 0x38740000, 0x38742000, 0x38744000, 0x38746000, 0x38748000, 0x3874A000, 0x3874C000, 0x3874E000, 0x38750000, 0x38752000, 0x38754000, 0x38756000, 0x38758000, 0x3875A000, 0x3875C000, 0x3875E000,
\r
881 0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876A000, 0x3876C000, 0x3876E000, 0x38770000, 0x38772000, 0x38774000, 0x38776000, 0x38778000, 0x3877A000, 0x3877C000, 0x3877E000,
\r
882 0x38780000, 0x38782000, 0x38784000, 0x38786000, 0x38788000, 0x3878A000, 0x3878C000, 0x3878E000, 0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879A000, 0x3879C000, 0x3879E000,
\r
883 0x387A0000, 0x387A2000, 0x387A4000, 0x387A6000, 0x387A8000, 0x387AA000, 0x387AC000, 0x387AE000, 0x387B0000, 0x387B2000, 0x387B4000, 0x387B6000, 0x387B8000, 0x387BA000, 0x387BC000, 0x387BE000,
\r
884 0x387C0000, 0x387C2000, 0x387C4000, 0x387C6000, 0x387C8000, 0x387CA000, 0x387CC000, 0x387CE000, 0x387D0000, 0x387D2000, 0x387D4000, 0x387D6000, 0x387D8000, 0x387DA000, 0x387DC000, 0x387DE000,
\r
885 0x387E0000, 0x387E2000, 0x387E4000, 0x387E6000, 0x387E8000, 0x387EA000, 0x387EC000, 0x387EE000, 0x387F0000, 0x387F2000, 0x387F4000, 0x387F6000, 0x387F8000, 0x387FA000, 0x387FC000, 0x387FE000 };
\r
886 static const uint32 exponent_table[64] = {
\r
887 0x00000000, 0x00800000, 0x01000000, 0x01800000, 0x02000000, 0x02800000, 0x03000000, 0x03800000, 0x04000000, 0x04800000, 0x05000000, 0x05800000, 0x06000000, 0x06800000, 0x07000000, 0x07800000,
\r
888 0x08000000, 0x08800000, 0x09000000, 0x09800000, 0x0A000000, 0x0A800000, 0x0B000000, 0x0B800000, 0x0C000000, 0x0C800000, 0x0D000000, 0x0D800000, 0x0E000000, 0x0E800000, 0x0F000000, 0x47800000,
\r
889 0x80000000, 0x80800000, 0x81000000, 0x81800000, 0x82000000, 0x82800000, 0x83000000, 0x83800000, 0x84000000, 0x84800000, 0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000,
\r
890 0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8A000000, 0x8A800000, 0x8B000000, 0x8B800000, 0x8C000000, 0x8C800000, 0x8D000000, 0x8D800000, 0x8E000000, 0x8E800000, 0x8F000000, 0xC7800000 };
\r
891 static const unsigned short offset_table[64] = {
\r
892 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
\r
893 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024 };
\r
894 uint32 bits = mantissa_table[offset_table[value>>10]+(value&0x3FF)] + exponent_table[value>>10];
\r
895 // return *reinterpret_cast<float*>(&bits); //violating strict aliasing!
\r
897 std::memcpy(&out, &bits, sizeof(float));
\r
901 /// Convert half-precision to IEEE double-precision.
\r
902 /// \param value binary representation of half-precision value
\r
903 /// \return double-precision value
\r
904 inline double half2float_impl(uint16 value, double, true_type)
\r
906 typedef bits<float>::type uint32;
\r
907 typedef bits<double>::type uint64;
\r
908 uint32 hi = static_cast<uint32>(value&0x8000) << 16;
\r
909 int abs = value & 0x7FFF;
\r
912 hi |= 0x3F000000 << static_cast<unsigned>(abs>=0x7C00);
\r
913 for(; abs<0x400; abs<<=1,hi-=0x100000) ;
\r
914 hi += static_cast<uint32>(abs) << 10;
\r
916 uint64 bits = static_cast<uint64>(hi) << 32;
\r
917 // return *reinterpret_cast<double*>(&bits); //violating strict aliasing!
\r
919 std::memcpy(&out, &bits, sizeof(double));
\r
923 /// Convert half-precision to non-IEEE floating point.
\r
924 /// \tparam T type to convert to (builtin integer type)
\r
925 /// \param value binary representation of half-precision value
\r
926 /// \return floating point value
\r
927 template<typename T> T half2float_impl(uint16 value, T, ...)
\r
930 int abs = value & 0x7FFF;
\r
932 out = std::numeric_limits<T>::has_quiet_NaN ? std::numeric_limits<T>::quiet_NaN() : T();
\r
933 else if(abs == 0x7C00)
\r
934 out = std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : std::numeric_limits<T>::max();
\r
935 else if(abs > 0x3FF)
\r
936 out = std::ldexp(static_cast<T>((abs&0x3FF)|0x400), (abs>>10)-25);
\r
938 out = std::ldexp(static_cast<T>(abs), -24);
\r
939 return (value&0x8000) ? -out : out;
\r
942 /// Convert half-precision to floating point.
\r
943 /// \tparam T type to convert to (builtin integer type)
\r
944 /// \param value binary representation of half-precision value
\r
945 /// \return floating point value
\r
946 template<typename T> T half2float(uint16 value)
\r
948 return half2float_impl(value, T(), bool_type<std::numeric_limits<T>::is_iec559&&sizeof(typename bits<T>::type)==sizeof(T)>());
\r
951 /// Convert half-precision floating point to integer.
\r
952 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
953 /// \tparam E `true` for round to even, `false` for round away from zero
\r
954 /// \tparam T type to convert to (buitlin integer type with at least 16 bits precision, excluding any implicit sign bits)
\r
955 /// \param value binary representation of half-precision value
\r
956 /// \return integral value
\r
957 template<std::float_round_style R,bool E,typename T> T half2int_impl(uint16 value)
\r
959 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
\r
960 static_assert(std::is_integral<T>::value, "half to int conversion only supports builtin integer types");
\r
962 unsigned int e = value & 0x7FFF;
\r
964 return (value&0x8000) ? std::numeric_limits<T>::min() : std::numeric_limits<T>::max();
\r
967 if(R == std::round_toward_infinity)
\r
968 return T(~(value>>15)&(e!=0));
\r
969 else if(R == std::round_toward_neg_infinity)
\r
970 return -T(value>0x8000);
\r
973 unsigned int m = (value&0x3FF) | 0x400;
\r
977 if(R == std::round_to_nearest)
\r
978 m += (1<<(24-e)) - (~(m>>(25-e))&E);
\r
979 else if(R == std::round_toward_infinity)
\r
980 m += ((value>>15)-1) & ((1<<(25-e))-1U);
\r
981 else if(R == std::round_toward_neg_infinity)
\r
982 m += -(value>>15) & ((1<<(25-e))-1U);
\r
987 return (value&0x8000) ? -static_cast<T>(m) : static_cast<T>(m);
\r
990 /// Convert half-precision floating point to integer.
\r
991 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
992 /// \tparam T type to convert to (buitlin integer type with at least 16 bits precision, excluding any implicit sign bits)
\r
993 /// \param value binary representation of half-precision value
\r
994 /// \return integral value
\r
995 template<std::float_round_style R,typename T> T half2int(uint16 value) { return half2int_impl<R,HALF_ROUND_TIES_TO_EVEN,T>(value); }
\r
997 /// Convert half-precision floating point to integer using round-to-nearest-away-from-zero.
\r
998 /// \tparam T type to convert to (buitlin integer type with at least 16 bits precision, excluding any implicit sign bits)
\r
999 /// \param value binary representation of half-precision value
\r
1000 /// \return integral value
\r
1001 template<typename T> T half2int_up(uint16 value) { return half2int_impl<std::round_to_nearest,0,T>(value); }
\r
1003 /// Round half-precision number to nearest integer value.
\r
1004 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
1005 /// \tparam E `true` for round to even, `false` for round away from zero
\r
1006 /// \param value binary representation of half-precision value
\r
1007 /// \return half-precision bits for nearest integral value
\r
1008 template<std::float_round_style R,bool E> uint16 round_half_impl(uint16 value)
\r
1010 unsigned int e = value & 0x7FFF;
\r
1011 uint16 result = value;
\r
1015 if(R == std::round_to_nearest)
\r
1016 result |= 0x3C00U & -(e>=(0x3800+E));
\r
1017 else if(R == std::round_toward_infinity)
\r
1018 result |= 0x3C00U & -(~(value>>15)&(e!=0));
\r
1019 else if(R == std::round_toward_neg_infinity)
\r
1020 result |= 0x3C00U & -(value>0x8000);
\r
1022 else if(e < 0x6400)
\r
1025 unsigned int mask = (1<<e) - 1;
\r
1026 if(R == std::round_to_nearest)
\r
1027 result += (1<<(e-1)) - (~(result>>e)&E);
\r
1028 else if(R == std::round_toward_infinity)
\r
1029 result += mask & ((value>>15)-1);
\r
1030 else if(R == std::round_toward_neg_infinity)
\r
1031 result += mask & -(value>>15);
\r
1037 /// Round half-precision number to nearest integer value.
\r
1038 /// \tparam R rounding mode to use, `std::round_indeterminate` for fastest rounding
\r
1039 /// \param value binary representation of half-precision value
\r
1040 /// \return half-precision bits for nearest integral value
\r
1041 template<std::float_round_style R> uint16 round_half(uint16 value) { return round_half_impl<R,HALF_ROUND_TIES_TO_EVEN>(value); }
\r
1043 /// Round half-precision number to nearest integer value using round-to-nearest-away-from-zero.
\r
1044 /// \param value binary representation of half-precision value
\r
1045 /// \return half-precision bits for nearest integral value
\r
1046 inline uint16 round_half_up(uint16 value) { return round_half_impl<std::round_to_nearest,0>(value); }
\r
1050 template<typename> struct unary_specialized;
\r
1051 template<typename,typename> struct binary_specialized;
\r
1052 template<typename,typename,std::float_round_style> struct half_caster;
\r
1055 /// Half-precision floating point type.
\r
1056 /// This class implements an IEEE-conformant half-precision floating point type with the usual arithmetic operators and
\r
1057 /// conversions. It is implicitly convertible to single-precision floating point, which makes artihmetic expressions and
\r
1058 /// functions with mixed-type operands to be of the most precise operand type. Additionally all arithmetic operations
\r
1059 /// (and many mathematical functions) are carried out in single-precision internally. All conversions from single- to
\r
1060 /// half-precision are done using the library's default rounding mode, but temporary results inside chained arithmetic
\r
1061 /// expressions are kept in single-precision as long as possible (while of course still maintaining a strong half-precision type).
\r
1063 /// According to the C++98/03 definition, the half type is not a POD type. But according to C++11's less strict and
\r
1064 /// extended definitions it is both a standard layout type and a trivially copyable type (even if not a POD type), which
\r
1065 /// means it can be standard-conformantly copied using raw binary copies. But in this context some more words about the
\r
1066 /// actual size of the type. Although the half is representing an IEEE 16-bit type, it does not neccessarily have to be of
\r
1067 /// exactly 16-bits size. But on any reasonable implementation the actual binary representation of this type will most
\r
1068 /// probably not ivolve any additional "magic" or padding beyond the simple binary representation of the underlying 16-bit
\r
1069 /// IEEE number, even if not strictly guaranteed by the standard. But even then it only has an actual size of 16 bits if
\r
1070 /// your C++ implementation supports an unsigned integer type of exactly 16 bits width. But this should be the case on
\r
1071 /// nearly any reasonable platform.
\r
1073 /// So if your C++ implementation is not totally exotic or imposes special alignment requirements, it is a reasonable
\r
1074 /// assumption that the data of a half is just comprised of the 2 bytes of the underlying IEEE representation.
\r
1077 friend struct detail::functions;
\r
1078 friend struct detail::unary_specialized<half>;
\r
1079 friend struct detail::binary_specialized<half,half>;
\r
1080 template<typename,typename,std::float_round_style> friend struct detail::half_caster;
\r
1081 friend class std::numeric_limits<half>;
\r
1082 #if HALF_ENABLE_CPP11_HASH
\r
1083 friend struct std::hash<half>;
\r
1085 #if HALF_ENABLE_CPP11_USER_LITERALS
\r
1086 friend half literal::operator""_h(long double);
\r
1090 /// Default constructor.
\r
1091 /// This initializes the half to 0. Although this does not match the builtin types' default-initialization semantics
\r
1092 /// and may be less efficient than no initialization, it is needed to provide proper value-initialization semantics.
\r
1093 HALF_CONSTEXPR half() HALF_NOEXCEPT : data_() {}
\r
1095 /// Copy constructor.
\r
1096 /// \tparam T type of concrete half expression
\r
1097 /// \param rhs half expression to copy from
\r
1098 half(detail::expr rhs) : data_(detail::float2half<round_style>(static_cast<float>(rhs))) {}
\r
1100 /// Conversion constructor.
\r
1101 /// \param rhs float to convert
\r
1102 explicit half(float rhs) : data_(detail::float2half<round_style>(rhs)) {}
\r
1104 /// Conversion to single-precision.
\r
1105 /// \return single precision value representing expression value
\r
1106 operator float() const { return detail::half2float<float>(data_); }
\r
1108 /// Assignment operator.
\r
1109 /// \tparam T type of concrete half expression
\r
1110 /// \param rhs half expression to copy from
\r
1111 /// \return reference to this half
\r
1112 half& operator=(detail::expr rhs) { return *this = static_cast<float>(rhs); }
\r
1114 /// Arithmetic assignment.
\r
1115 /// \tparam T type of concrete half expression
\r
1116 /// \param rhs half expression to add
\r
1117 /// \return reference to this half
\r
1118 template<typename T> typename detail::enable<half&,T>::type operator+=(T rhs) { return *this += static_cast<float>(rhs); }
\r
1120 /// Arithmetic assignment.
\r
1121 /// \tparam T type of concrete half expression
\r
1122 /// \param rhs half expression to subtract
\r
1123 /// \return reference to this half
\r
1124 template<typename T> typename detail::enable<half&,T>::type operator-=(T rhs) { return *this -= static_cast<float>(rhs); }
\r
1126 /// Arithmetic assignment.
\r
1127 /// \tparam T type of concrete half expression
\r
1128 /// \param rhs half expression to multiply with
\r
1129 /// \return reference to this half
\r
1130 template<typename T> typename detail::enable<half&,T>::type operator*=(T rhs) { return *this *= static_cast<float>(rhs); }
\r
1132 /// Arithmetic assignment.
\r
1133 /// \tparam T type of concrete half expression
\r
1134 /// \param rhs half expression to divide by
\r
1135 /// \return reference to this half
\r
1136 template<typename T> typename detail::enable<half&,T>::type operator/=(T rhs) { return *this /= static_cast<float>(rhs); }
\r
1138 /// Assignment operator.
\r
1139 /// \param rhs single-precision value to copy from
\r
1140 /// \return reference to this half
\r
1141 half& operator=(float rhs) { data_ = detail::float2half<round_style>(rhs); return *this; }
\r
1143 /// Arithmetic assignment.
\r
1144 /// \param rhs single-precision value to add
\r
1145 /// \return reference to this half
\r
1146 half& operator+=(float rhs) { data_ = detail::float2half<round_style>(detail::half2float<float>(data_)+rhs); return *this; }
\r
1148 /// Arithmetic assignment.
\r
1149 /// \param rhs single-precision value to subtract
\r
1150 /// \return reference to this half
\r
1151 half& operator-=(float rhs) { data_ = detail::float2half<round_style>(detail::half2float<float>(data_)-rhs); return *this; }
\r
1153 /// Arithmetic assignment.
\r
1154 /// \param rhs single-precision value to multiply with
\r
1155 /// \return reference to this half
\r
1156 half& operator*=(float rhs) { data_ = detail::float2half<round_style>(detail::half2float<float>(data_)*rhs); return *this; }
\r
1158 /// Arithmetic assignment.
\r
1159 /// \param rhs single-precision value to divide by
\r
1160 /// \return reference to this half
\r
1161 half& operator/=(float rhs) { data_ = detail::float2half<round_style>(detail::half2float<float>(data_)/rhs); return *this; }
\r
1163 /// Prefix increment.
\r
1164 /// \return incremented half value
\r
1165 half& operator++() { return *this += 1.0f; }
\r
1167 /// Prefix decrement.
\r
1168 /// \return decremented half value
\r
1169 half& operator--() { return *this -= 1.0f; }
\r
1171 /// Postfix increment.
\r
1172 /// \return non-incremented half value
\r
1173 half operator++(int) { half out(*this); ++*this; return out; }
\r
1175 /// Postfix decrement.
\r
1176 /// \return non-decremented half value
\r
1177 half operator--(int) { half out(*this); --*this; return out; }
\r
1180 /// Rounding mode to use
\r
1181 static const std::float_round_style round_style = (std::float_round_style)(HALF_ROUND_STYLE);
\r
1184 /// \param bits binary representation to set half to
\r
1185 HALF_CONSTEXPR half(detail::binary_t, detail::uint16 bits) HALF_NOEXCEPT : data_(bits) {}
\r
1187 /// Internal binary representation
\r
1188 detail::uint16 data_;
\r
1191 #if HALF_ENABLE_CPP11_USER_LITERALS
\r
1195 /// While this returns an actual half-precision value, half literals can unfortunately not be constant expressions due
\r
1196 /// to rather involved conversions.
\r
1197 /// \param value literal value
\r
1198 /// \return half with given value (if representable)
\r
1199 inline half operator""_h(long double value) { return half(detail::binary, detail::float2half<half::round_style>(value)); }
\r
1205 /// Wrapper implementing unspecialized half-precision functions.
\r
1208 /// Addition implementation.
\r
1209 /// \param x first operand
\r
1210 /// \param y second operand
\r
1211 /// \return Half-precision sum stored in single-precision
\r
1212 static expr plus(float x, float y) { return expr(x+y); }
\r
1214 /// Subtraction implementation.
\r
1215 /// \param x first operand
\r
1216 /// \param y second operand
\r
1217 /// \return Half-precision difference stored in single-precision
\r
1218 static expr minus(float x, float y) { return expr(x-y); }
\r
1220 /// Multiplication implementation.
\r
1221 /// \param x first operand
\r
1222 /// \param y second operand
\r
1223 /// \return Half-precision product stored in single-precision
\r
1224 static expr multiplies(float x, float y) { return expr(x*y); }
\r
1226 /// Division implementation.
\r
1227 /// \param x first operand
\r
1228 /// \param y second operand
\r
1229 /// \return Half-precision quotient stored in single-precision
\r
1230 static expr divides(float x, float y) { return expr(x/y); }
\r
1232 /// Output implementation.
\r
1233 /// \param out stream to write to
\r
1234 /// \param arg value to write
\r
1235 /// \return reference to stream
\r
1236 template<typename charT,typename traits> static std::basic_ostream<charT,traits>& write(std::basic_ostream<charT,traits> &out, float arg) { return out << arg; }
\r
1238 /// Input implementation.
\r
1239 /// \param in stream to read from
\r
1240 /// \param arg half to read into
\r
1241 /// \return reference to stream
\r
1242 template<typename charT,typename traits> static std::basic_istream<charT,traits>& read(std::basic_istream<charT,traits> &in, half &arg)
\r
1250 /// Modulo implementation.
\r
1251 /// \param x first operand
\r
1252 /// \param y second operand
\r
1253 /// \return Half-precision division remainder stored in single-precision
\r
1254 static expr fmod(float x, float y) { return expr(std::fmod(x, y)); }
\r
1256 /// Remainder implementation.
\r
1257 /// \param x first operand
\r
1258 /// \param y second operand
\r
1259 /// \return Half-precision division remainder stored in single-precision
\r
1260 static expr remainder(float x, float y)
\r
1262 #if HALF_ENABLE_CPP11_CMATH
\r
1263 return expr(std::remainder(x, y));
\r
1265 if(builtin_isnan(x) || builtin_isnan(y))
\r
1266 return expr(std::numeric_limits<float>::quiet_NaN());
\r
1267 float ax = std::fabs(x), ay = std::fabs(y);
\r
1268 if(ax >= 65536.0f || ay < std::ldexp(1.0f, -24))
\r
1269 return expr(std::numeric_limits<float>::quiet_NaN());
\r
1270 if(ay >= 65536.0f)
\r
1273 return expr(builtin_signbit(x) ? -0.0f : 0.0f);
\r
1274 ax = std::fmod(ax, ay+ay);
\r
1275 float y2 = 0.5f * ay;
\r
1282 return expr(builtin_signbit(x) ? -ax : ax);
\r
1286 /// Remainder implementation.
\r
1287 /// \param x first operand
\r
1288 /// \param y second operand
\r
1289 /// \param quo address to store quotient bits at
\r
1290 /// \return Half-precision division remainder stored in single-precision
\r
1291 static expr remquo(float x, float y, int *quo)
\r
1293 #if HALF_ENABLE_CPP11_CMATH
\r
1294 return expr(std::remquo(x, y, quo));
\r
1296 if(builtin_isnan(x) || builtin_isnan(y))
\r
1297 return expr(std::numeric_limits<float>::quiet_NaN());
\r
1298 bool sign = builtin_signbit(x), qsign = static_cast<bool>(sign^builtin_signbit(y));
\r
1299 float ax = std::fabs(x), ay = std::fabs(y);
\r
1300 if(ax >= 65536.0f || ay < std::ldexp(1.0f, -24))
\r
1301 return expr(std::numeric_limits<float>::quiet_NaN());
\r
1302 if(ay >= 65536.0f)
\r
1305 return *quo = qsign ? -1 : 1, expr(sign ? -0.0f : 0.0f);
\r
1306 ax = std::fmod(ax, 8.0f*ay);
\r
1308 if(ax >= 4.0f * ay)
\r
1313 if(ax >= 2.0f * ay)
\r
1318 float y2 = 0.5f * ay;
\r
1329 return *quo = qsign ? -cquo : cquo, expr(sign ? -ax : ax);
\r
1333 /// Positive difference implementation.
\r
1334 /// \param x first operand
\r
1335 /// \param y second operand
\r
1336 /// \return Positive difference stored in single-precision
\r
1337 static expr fdim(float x, float y)
\r
1339 #if HALF_ENABLE_CPP11_CMATH
\r
1340 return expr(std::fdim(x, y));
\r
1342 return expr((x<=y) ? 0.0f : (x-y));
\r
1346 /// Fused multiply-add implementation.
\r
1347 /// \param x first operand
\r
1348 /// \param y second operand
\r
1349 /// \param z third operand
\r
1350 /// \return \a x * \a y + \a z stored in single-precision
\r
1351 static expr fma(float x, float y, float z)
\r
1353 #if HALF_ENABLE_CPP11_CMATH && defined(FP_FAST_FMAF)
\r
1354 return expr(std::fma(x, y, z));
\r
1356 return expr(x*y+z);
\r
1361 /// \return Half-precision quiet NaN
\r
1362 static half nanh() { return half(binary, 0x7FFF); }
\r
1364 /// Exponential implementation.
\r
1365 /// \param arg function argument
\r
1366 /// \return function value stored in single-preicision
\r
1367 static expr exp(float arg) { return expr(std::exp(arg)); }
\r
1369 /// Exponential implementation.
\r
1370 /// \param arg function argument
\r
1371 /// \return function value stored in single-preicision
\r
1372 static expr expm1(float arg)
\r
1374 #if HALF_ENABLE_CPP11_CMATH
\r
1375 return expr(std::expm1(arg));
\r
1377 return expr(static_cast<float>(std::exp(static_cast<double>(arg))-1.0));
\r
1381 /// Binary exponential implementation.
\r
1382 /// \param arg function argument
\r
1383 /// \return function value stored in single-preicision
\r
1384 static expr exp2(float arg)
\r
1386 #if HALF_ENABLE_CPP11_CMATH
\r
1387 return expr(std::exp2(arg));
\r
1389 return expr(static_cast<float>(std::exp(arg*0.69314718055994530941723212145818)));
\r
1393 /// Logarithm implementation.
\r
1394 /// \param arg function argument
\r
1395 /// \return function value stored in single-preicision
\r
1396 static expr log(float arg) { return expr(std::log(arg)); }
\r
1398 /// Common logarithm implementation.
\r
1399 /// \param arg function argument
\r
1400 /// \return function value stored in single-preicision
\r
1401 static expr log10(float arg) { return expr(std::log10(arg)); }
\r
1403 /// Logarithm implementation.
\r
1404 /// \param arg function argument
\r
1405 /// \return function value stored in single-preicision
\r
1406 static expr log1p(float arg)
\r
1408 #if HALF_ENABLE_CPP11_CMATH
\r
1409 return expr(std::log1p(arg));
\r
1411 return expr(static_cast<float>(std::log(1.0+arg)));
\r
1415 /// Binary logarithm implementation.
\r
1416 /// \param arg function argument
\r
1417 /// \return function value stored in single-preicision
\r
1418 static expr log2(float arg)
\r
1420 #if HALF_ENABLE_CPP11_CMATH
\r
1421 return expr(std::log2(arg));
\r
1423 return expr(static_cast<float>(std::log(static_cast<double>(arg))*1.4426950408889634073599246810019));
\r
1427 /// Square root implementation.
\r
1428 /// \param arg function argument
\r
1429 /// \return function value stored in single-preicision
\r
1430 static expr sqrt(float arg) { return expr(std::sqrt(arg)); }
\r
1432 /// Cubic root implementation.
\r
1433 /// \param arg function argument
\r
1434 /// \return function value stored in single-preicision
\r
1435 static expr cbrt(float arg)
\r
1437 #if HALF_ENABLE_CPP11_CMATH
\r
1438 return expr(std::cbrt(arg));
\r
1440 if(builtin_isnan(arg) || builtin_isinf(arg))
\r
1442 return expr(builtin_signbit(arg) ? -static_cast<float>(std::pow(-static_cast<double>(arg), 1.0/3.0)) :
\r
1443 static_cast<float>(std::pow(static_cast<double>(arg), 1.0/3.0)));
\r
1447 /// Hypotenuse implementation.
\r
1448 /// \param x first argument
\r
1449 /// \param y second argument
\r
1450 /// \return function value stored in single-preicision
\r
1451 static expr hypot(float x, float y)
\r
1453 #if HALF_ENABLE_CPP11_CMATH
\r
1454 return expr(std::hypot(x, y));
\r
1456 return expr((builtin_isinf(x) || builtin_isinf(y)) ? std::numeric_limits<float>::infinity() :
\r
1457 static_cast<float>(std::sqrt(static_cast<double>(x)*x+static_cast<double>(y)*y)));
\r
1461 /// Power implementation.
\r
1462 /// \param base value to exponentiate
\r
1463 /// \param exp power to expontiate to
\r
1464 /// \return function value stored in single-preicision
\r
1465 static expr pow(float base, float exp) { return expr(std::pow(base, exp)); }
\r
1467 /// Sine implementation.
\r
1468 /// \param arg function argument
\r
1469 /// \return function value stored in single-preicision
\r
1470 static expr sin(float arg) { return expr(std::sin(arg)); }
\r
1472 /// Cosine implementation.
\r
1473 /// \param arg function argument
\r
1474 /// \return function value stored in single-preicision
\r
1475 static expr cos(float arg) { return expr(std::cos(arg)); }
\r
1477 /// Tan implementation.
\r
1478 /// \param arg function argument
\r
1479 /// \return function value stored in single-preicision
\r
1480 static expr tan(float arg) { return expr(std::tan(arg)); }
\r
1482 /// Arc sine implementation.
\r
1483 /// \param arg function argument
\r
1484 /// \return function value stored in single-preicision
\r
1485 static expr asin(float arg) { return expr(std::asin(arg)); }
\r
1487 /// Arc cosine implementation.
\r
1488 /// \param arg function argument
\r
1489 /// \return function value stored in single-preicision
\r
1490 static expr acos(float arg) { return expr(std::acos(arg)); }
\r
1492 /// Arc tangent implementation.
\r
1493 /// \param arg function argument
\r
1494 /// \return function value stored in single-preicision
\r
1495 static expr atan(float arg) { return expr(std::atan(arg)); }
\r
1497 /// Arc tangent implementation.
\r
1498 /// \param x first argument
\r
1499 /// \param y second argument
\r
1500 /// \return function value stored in single-preicision
\r
1501 static expr atan2(float x, float y) { return expr(std::atan2(x, y)); }
\r
1503 /// Hyperbolic sine implementation.
\r
1504 /// \param arg function argument
\r
1505 /// \return function value stored in single-preicision
\r
1506 static expr sinh(float arg) { return expr(std::sinh(arg)); }
\r
1508 /// Hyperbolic cosine implementation.
\r
1509 /// \param arg function argument
\r
1510 /// \return function value stored in single-preicision
\r
1511 static expr cosh(float arg) { return expr(std::cosh(arg)); }
\r
1513 /// Hyperbolic tangent implementation.
\r
1514 /// \param arg function argument
\r
1515 /// \return function value stored in single-preicision
\r
1516 static expr tanh(float arg) { return expr(std::tanh(arg)); }
\r
1518 /// Hyperbolic area sine implementation.
\r
1519 /// \param arg function argument
\r
1520 /// \return function value stored in single-preicision
\r
1521 static expr asinh(float arg)
\r
1523 #if HALF_ENABLE_CPP11_CMATH
\r
1524 return expr(std::asinh(arg));
\r
1526 return expr((arg==-std::numeric_limits<float>::infinity()) ? arg : static_cast<float>(std::log(arg+std::sqrt(arg*arg+1.0))));
\r
1530 /// Hyperbolic area cosine implementation.
\r
1531 /// \param arg function argument
\r
1532 /// \return function value stored in single-preicision
\r
1533 static expr acosh(float arg)
\r
1535 #if HALF_ENABLE_CPP11_CMATH
\r
1536 return expr(std::acosh(arg));
\r
1538 return expr((arg<-1.0f) ? std::numeric_limits<float>::quiet_NaN() : static_cast<float>(std::log(arg+std::sqrt(arg*arg-1.0))));
\r
1542 /// Hyperbolic area tangent implementation.
\r
1543 /// \param arg function argument
\r
1544 /// \return function value stored in single-preicision
\r
1545 static expr atanh(float arg)
\r
1547 #if HALF_ENABLE_CPP11_CMATH
\r
1548 return expr(std::atanh(arg));
\r
1550 return expr(static_cast<float>(0.5*std::log((1.0+arg)/(1.0-arg))));
\r
1554 /// Error function implementation.
\r
1555 /// \param arg function argument
\r
1556 /// \return function value stored in single-preicision
\r
1557 static expr erf(float arg)
\r
1559 #if HALF_ENABLE_CPP11_CMATH
\r
1560 return expr(std::erf(arg));
\r
1562 return expr(static_cast<float>(erf(static_cast<double>(arg))));
\r
1566 /// Complementary implementation.
\r
1567 /// \param arg function argument
\r
1568 /// \return function value stored in single-preicision
\r
1569 static expr erfc(float arg)
\r
1571 #if HALF_ENABLE_CPP11_CMATH
\r
1572 return expr(std::erfc(arg));
\r
1574 return expr(static_cast<float>(1.0-erf(static_cast<double>(arg))));
\r
1578 /// Gamma logarithm implementation.
\r
1579 /// \param arg function argument
\r
1580 /// \return function value stored in single-preicision
\r
1581 static expr lgamma(float arg)
\r
1583 #if HALF_ENABLE_CPP11_CMATH
\r
1584 return expr(std::lgamma(arg));
\r
1586 if(builtin_isinf(arg))
\r
1587 return expr(std::numeric_limits<float>::infinity());
\r
1590 float i, f = std::modf(-arg, &i);
\r
1592 return expr(std::numeric_limits<float>::infinity());
\r
1593 return expr(static_cast<float>(1.1447298858494001741434273513531-
\r
1594 std::log(std::abs(std::sin(3.1415926535897932384626433832795*f)))-lgamma(1.0-arg)));
\r
1596 return expr(static_cast<float>(lgamma(static_cast<double>(arg))));
\r
1600 /// Gamma implementation.
\r
1601 /// \param arg function argument
\r
1602 /// \return function value stored in single-preicision
\r
1603 static expr tgamma(float arg)
\r
1605 #if HALF_ENABLE_CPP11_CMATH
\r
1606 return expr(std::tgamma(arg));
\r
1609 return builtin_signbit(arg) ? expr(-std::numeric_limits<float>::infinity()) : expr(std::numeric_limits<float>::infinity());
\r
1612 float i, f = std::modf(-arg, &i);
\r
1614 return expr(std::numeric_limits<float>::quiet_NaN());
\r
1615 double value = 3.1415926535897932384626433832795 / (std::sin(3.1415926535897932384626433832795*f)*std::exp(lgamma(1.0-arg)));
\r
1616 return expr(static_cast<float>((std::fmod(i, 2.0f)==0.0f) ? -value : value));
\r
1618 if(builtin_isinf(arg))
\r
1620 return expr(static_cast<float>(std::exp(lgamma(static_cast<double>(arg)))));
\r
1624 /// Floor implementation.
\r
1625 /// \param arg value to round
\r
1626 /// \return rounded value
\r
1627 static half floor(half arg) { return half(binary, round_half<std::round_toward_neg_infinity>(arg.data_)); }
\r
1629 /// Ceiling implementation.
\r
1630 /// \param arg value to round
\r
1631 /// \return rounded value
\r
1632 static half ceil(half arg) { return half(binary, round_half<std::round_toward_infinity>(arg.data_)); }
\r
1634 /// Truncation implementation.
\r
1635 /// \param arg value to round
\r
1636 /// \return rounded value
\r
1637 static half trunc(half arg) { return half(binary, round_half<std::round_toward_zero>(arg.data_)); }
\r
1639 /// Nearest integer implementation.
\r
1640 /// \param arg value to round
\r
1641 /// \return rounded value
\r
1642 static half round(half arg) { return half(binary, round_half_up(arg.data_)); }
\r
1644 /// Nearest integer implementation.
\r
1645 /// \param arg value to round
\r
1646 /// \return rounded value
\r
1647 static long lround(half arg) { return detail::half2int_up<long>(arg.data_); }
\r
1649 /// Nearest integer implementation.
\r
1650 /// \param arg value to round
\r
1651 /// \return rounded value
\r
1652 static half rint(half arg) { return half(binary, round_half<half::round_style>(arg.data_)); }
\r
1654 /// Nearest integer implementation.
\r
1655 /// \param arg value to round
\r
1656 /// \return rounded value
\r
1657 static long lrint(half arg) { return detail::half2int<half::round_style,long>(arg.data_); }
\r
1659 #if HALF_ENABLE_CPP11_LONG_LONG
\r
1660 /// Nearest integer implementation.
\r
1661 /// \param arg value to round
\r
1662 /// \return rounded value
\r
1663 static long long llround(half arg) { return detail::half2int_up<long long>(arg.data_); }
\r
1665 /// Nearest integer implementation.
\r
1666 /// \param arg value to round
\r
1667 /// \return rounded value
\r
1668 static long long llrint(half arg) { return detail::half2int<half::round_style,long long>(arg.data_); }
\r
1671 /// Decompression implementation.
\r
1672 /// \param arg number to decompress
\r
1673 /// \param exp address to store exponent at
\r
1674 /// \return normalized significant
\r
1675 static half frexp(half arg, int *exp)
\r
1677 int m = arg.data_ & 0x7FFF, e = -14;
\r
1678 if(m >= 0x7C00 || !m)
\r
1679 return *exp = 0, arg;
\r
1680 for(; m<0x400; m<<=1,--e) ;
\r
1681 return *exp = e+(m>>10), half(binary, (arg.data_&0x8000)|0x3800|(m&0x3FF));
\r
1684 /// Decompression implementation.
\r
1685 /// \param arg number to decompress
\r
1686 /// \param iptr address to store integer part at
\r
1687 /// \return fractional part
\r
1688 static half modf(half arg, half *iptr)
\r
1690 unsigned int e = arg.data_ & 0x7FFF;
\r
1692 return *iptr = arg, half(binary, arg.data_&(0x8000U|-(e>0x7C00)));
\r
1694 return iptr->data_ = arg.data_ & 0x8000, arg;
\r
1696 unsigned int mask = (1<<(25-e)) - 1, m = arg.data_ & mask;
\r
1697 iptr->data_ = arg.data_ & ~mask;
\r
1699 return half(binary, arg.data_&0x8000);
\r
1700 for(; m<0x400; m<<=1,--e) ;
\r
1701 return half(binary, static_cast<uint16>((arg.data_&0x8000)|(e<<10)|(m&0x3FF)));
\r
1704 /// Scaling implementation.
\r
1705 /// \param arg number to scale
\r
1706 /// \param exp power of two to scale by
\r
1707 /// \return scaled number
\r
1708 static half scalbln(half arg, long exp)
\r
1710 unsigned int m = arg.data_ & 0x7FFF;
\r
1711 if(m >= 0x7C00 || !m)
\r
1713 for(; m<0x400; m<<=1,--exp) ;
\r
1715 uint16 value = arg.data_ & 0x8000;
\r
1718 if(half::round_style == std::round_toward_zero)
\r
1720 else if(half::round_style == std::round_toward_infinity)
\r
1721 value |= 0x7C00 - (value>>15);
\r
1722 else if(half::round_style == std::round_toward_neg_infinity)
\r
1723 value |= 0x7BFF + (value>>15);
\r
1728 value |= (exp<<10) | (m&0x3FF);
\r
1729 else if(exp > -11)
\r
1731 m = (m&0x3FF) | 0x400;
\r
1732 if(half::round_style == std::round_to_nearest)
\r
1735 #if HALF_ROUND_TIES_TO_EVEN
\r
1736 m -= (m>>(1-exp)) & 1;
\r
1739 else if(half::round_style == std::round_toward_infinity)
\r
1740 m += ((value>>15)-1) & ((1<<(1-exp))-1U);
\r
1741 else if(half::round_style == std::round_toward_neg_infinity)
\r
1742 m += -(value>>15) & ((1<<(1-exp))-1U);
\r
1743 value |= m >> (1-exp);
\r
1745 else if(half::round_style == std::round_toward_infinity)
\r
1746 value -= (value>>15) - 1;
\r
1747 else if(half::round_style == std::round_toward_neg_infinity)
\r
1748 value += value >> 15;
\r
1749 return half(binary, value);
\r
1752 /// Exponent implementation.
\r
1753 /// \param arg number to query
\r
1754 /// \return floating point exponent
\r
1755 static int ilogb(half arg)
\r
1757 int abs = arg.data_ & 0x7FFF;
\r
1762 int exp = (abs>>10) - 15;
\r
1764 for(; abs<0x200; abs<<=1,--exp) ;
\r
1768 return FP_ILOGBNAN;
\r
1772 /// Exponent implementation.
\r
1773 /// \param arg number to query
\r
1774 /// \return floating point exponent
\r
1775 static half logb(half arg)
\r
1777 int abs = arg.data_ & 0x7FFF;
\r
1779 return half(binary, 0xFC00);
\r
1782 int exp = (abs>>10) - 15;
\r
1784 for(; abs<0x200; abs<<=1,--exp) ;
\r
1785 uint16 bits = (exp<0) << 15;
\r
1788 unsigned int m = std::abs(exp) << 6, e = 18;
\r
1789 for(; m<0x400; m<<=1,--e) ;
\r
1790 bits |= (e<<10) + m;
\r
1792 return half(binary, bits);
\r
1796 return half(binary, 0x7C00);
\r
1799 /// Enumeration implementation.
\r
1800 /// \param from number to increase/decrease
\r
1801 /// \param to direction to enumerate into
\r
1802 /// \return next representable number
\r
1803 static half nextafter(half from, half to)
\r
1805 uint16 fabs = from.data_ & 0x7FFF, tabs = to.data_ & 0x7FFF;
\r
1808 if(tabs > 0x7C00 || from.data_ == to.data_ || !(fabs|tabs))
\r
1811 return half(binary, (to.data_&0x8000)+1);
\r
1812 bool lt = ((fabs==from.data_) ? static_cast<int>(fabs) : -static_cast<int>(fabs)) <
\r
1813 ((tabs==to.data_) ? static_cast<int>(tabs) : -static_cast<int>(tabs));
\r
1814 return half(binary, from.data_+(((from.data_>>15)^static_cast<unsigned>(lt))<<1)-1);
\r
1817 /// Enumeration implementation.
\r
1818 /// \param from number to increase/decrease
\r
1819 /// \param to direction to enumerate into
\r
1820 /// \return next representable number
\r
1821 static half nexttoward(half from, long double to)
\r
1825 long double lfrom = static_cast<long double>(from);
\r
1826 if(builtin_isnan(to) || lfrom == to)
\r
1827 return half(static_cast<float>(to));
\r
1828 if(!(from.data_&0x7FFF))
\r
1829 return half(binary, (static_cast<detail::uint16>(builtin_signbit(to))<<15)+1);
\r
1830 return half(binary, from.data_+(((from.data_>>15)^static_cast<unsigned>(lfrom<to))<<1)-1);
\r
1833 /// Sign implementation
\r
1834 /// \param x first operand
\r
1835 /// \param y second operand
\r
1836 /// \return composed value
\r
1837 static half copysign(half x, half y) { return half(binary, x.data_^((x.data_^y.data_)&0x8000)); }
\r
1839 /// Classification implementation.
\r
1840 /// \param arg value to classify
\r
1841 /// \retval true if infinite number
\r
1842 /// \retval false else
\r
1843 static int fpclassify(half arg)
\r
1845 unsigned int abs = arg.data_ & 0x7FFF;
\r
1846 return abs ? ((abs>0x3FF) ? ((abs>=0x7C00) ? ((abs>0x7C00) ? FP_NAN : FP_INFINITE) : FP_NORMAL) :FP_SUBNORMAL) : FP_ZERO;
\r
1849 /// Classification implementation.
\r
1850 /// \param arg value to classify
\r
1851 /// \retval true if finite number
\r
1852 /// \retval false else
\r
1853 static bool isfinite(half arg) { return (arg.data_&0x7C00) != 0x7C00; }
\r
1855 /// Classification implementation.
\r
1856 /// \param arg value to classify
\r
1857 /// \retval true if infinite number
\r
1858 /// \retval false else
\r
1859 static bool isinf(half arg) { return (arg.data_&0x7FFF) == 0x7C00; }
\r
1861 /// Classification implementation.
\r
1862 /// \param arg value to classify
\r
1863 /// \retval true if not a number
\r
1864 /// \retval false else
\r
1865 static bool isnan(half arg) { return (arg.data_&0x7FFF) > 0x7C00; }
\r
1867 /// Classification implementation.
\r
1868 /// \param arg value to classify
\r
1869 /// \retval true if normal number
\r
1870 /// \retval false else
\r
1871 static bool isnormal(half arg) { return ((arg.data_&0x7C00)!=0) & ((arg.data_&0x7C00)!=0x7C00); }
\r
1873 /// Sign bit implementation.
\r
1874 /// \param arg value to check
\r
1875 /// \retval true if signed
\r
1876 /// \retval false if unsigned
\r
1877 static bool signbit(half arg) { return (arg.data_&0x8000) != 0; }
\r
1879 /// Comparison implementation.
\r
1880 /// \param x first operand
\r
1881 /// \param y second operand
\r
1882 /// \retval true if operands equal
\r
1883 /// \retval false else
\r
1884 static bool isequal(half x, half y) { return (x.data_==y.data_ || !((x.data_|y.data_)&0x7FFF)) && !isnan(x); }
\r
1886 /// Comparison implementation.
\r
1887 /// \param x first operand
\r
1888 /// \param y second operand
\r
1889 /// \retval true if operands not equal
\r
1890 /// \retval false else
\r
1891 static bool isnotequal(half x, half y) { return (x.data_!=y.data_ && ((x.data_|y.data_)&0x7FFF)) || isnan(x); }
\r
1893 /// Comparison implementation.
\r
1894 /// \param x first operand
\r
1895 /// \param y second operand
\r
1896 /// \retval true if \a x > \a y
\r
1897 /// \retval false else
\r
1898 static bool isgreater(half x, half y)
\r
1900 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
1901 return xabs<=0x7C00 && yabs<=0x7C00 && (((xabs==x.data_) ? xabs : -xabs) > ((yabs==y.data_) ? yabs : -yabs));
\r
1904 /// Comparison implementation.
\r
1905 /// \param x first operand
\r
1906 /// \param y second operand
\r
1907 /// \retval true if \a x >= \a y
\r
1908 /// \retval false else
\r
1909 static bool isgreaterequal(half x, half y)
\r
1911 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
1912 return xabs<=0x7C00 && yabs<=0x7C00 && (((xabs==x.data_) ? xabs : -xabs) >= ((yabs==y.data_) ? yabs : -yabs));
\r
1915 /// Comparison implementation.
\r
1916 /// \param x first operand
\r
1917 /// \param y second operand
\r
1918 /// \retval true if \a x < \a y
\r
1919 /// \retval false else
\r
1920 static bool isless(half x, half y)
\r
1922 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
1923 return xabs<=0x7C00 && yabs<=0x7C00 && (((xabs==x.data_) ? xabs : -xabs) < ((yabs==y.data_) ? yabs : -yabs));
\r
1926 /// Comparison implementation.
\r
1927 /// \param x first operand
\r
1928 /// \param y second operand
\r
1929 /// \retval true if \a x <= \a y
\r
1930 /// \retval false else
\r
1931 static bool islessequal(half x, half y)
\r
1933 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
1934 return xabs<=0x7C00 && yabs<=0x7C00 && (((xabs==x.data_) ? xabs : -xabs) <= ((yabs==y.data_) ? yabs : -yabs));
\r
1937 /// Comparison implementation.
\r
1938 /// \param x first operand
\r
1939 /// \param y second operand
\r
1940 /// \retval true if either \a x > \a y nor \a x < \a y
\r
1941 /// \retval false else
\r
1942 static bool islessgreater(half x, half y)
\r
1944 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
1945 if(xabs > 0x7C00 || yabs > 0x7C00)
\r
1947 int a = (xabs==x.data_) ? xabs : -xabs, b = (yabs==y.data_) ? yabs : -yabs;
\r
1948 return a < b || a > b;
\r
1951 /// Comparison implementation.
\r
1952 /// \param x first operand
\r
1953 /// \param y second operand
\r
1954 /// \retval true if operand unordered
\r
1955 /// \retval false else
\r
1956 static bool isunordered(half x, half y) { return isnan(x) || isnan(y); }
\r
1959 static double erf(double arg)
\r
1961 if(builtin_isinf(arg))
\r
1962 return (arg<0.0) ? -1.0 : 1.0;
\r
1963 double x2 = arg * arg, ax2 = 0.147 * x2, value = std::sqrt(1.0-std::exp(-x2*(1.2732395447351626861510701069801+ax2)/(1.0+ax2)));
\r
1964 return builtin_signbit(arg) ? -value : value;
\r
1967 static double lgamma(double arg)
\r
1970 for(; arg<8.0; ++arg) v *= arg;
\r
1971 double w = 1.0 / (arg*arg);
\r
1972 return (((((((-0.02955065359477124183006535947712*w+0.00641025641025641025641025641026)*w+
\r
1973 -0.00191752691752691752691752691753)*w+8.4175084175084175084175084175084e-4)*w+
\r
1974 -5.952380952380952380952380952381e-4)*w+7.9365079365079365079365079365079e-4)*w+
\r
1975 -0.00277777777777777777777777777778)*w+0.08333333333333333333333333333333)/arg +
\r
1976 0.91893853320467274178032973640562 - std::log(v) - arg + (arg-0.5) * std::log(arg);
\r
1980 /// Wrapper for unary half-precision functions needing specialization for individual argument types.
\r
1981 /// \tparam T argument type
\r
1982 template<typename T> struct unary_specialized
\r
1984 /// Negation implementation.
\r
1985 /// \param arg value to negate
\r
1986 /// \return negated value
\r
1987 static HALF_CONSTEXPR half negate(half arg) { return half(binary, arg.data_^0x8000); }
\r
1989 /// Absolute value implementation.
\r
1990 /// \param arg function argument
\r
1991 /// \return absolute value
\r
1992 static half fabs(half arg) { return half(binary, arg.data_&0x7FFF); }
\r
1994 template<> struct unary_specialized<expr>
\r
1996 static HALF_CONSTEXPR expr negate(float arg) { return expr(-arg); }
\r
1997 static expr fabs(float arg) { return expr(std::fabs(arg)); }
\r
2000 /// Wrapper for binary half-precision functions needing specialization for individual argument types.
\r
2001 /// \tparam T first argument type
\r
2002 /// \tparam U first argument type
\r
2003 template<typename T,typename U> struct binary_specialized
\r
2005 /// Minimum implementation.
\r
2006 /// \param x first operand
\r
2007 /// \param y second operand
\r
2008 /// \return minimum value
\r
2009 static expr fmin(float x, float y)
\r
2011 #if HALF_ENABLE_CPP11_CMATH
\r
2012 return expr(std::fmin(x, y));
\r
2014 if(builtin_isnan(x))
\r
2016 if(builtin_isnan(y))
\r
2018 return expr(std::min(x, y));
\r
2022 /// Maximum implementation.
\r
2023 /// \param x first operand
\r
2024 /// \param y second operand
\r
2025 /// \return maximum value
\r
2026 static expr fmax(float x, float y)
\r
2028 #if HALF_ENABLE_CPP11_CMATH
\r
2029 return expr(std::fmax(x, y));
\r
2031 if(builtin_isnan(x))
\r
2033 if(builtin_isnan(y))
\r
2035 return expr(std::max(x, y));
\r
2039 template<> struct binary_specialized<half,half>
\r
2041 static half fmin(half x, half y)
\r
2043 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
2048 return (((xabs==x.data_) ? xabs : -xabs) > ((yabs==y.data_) ? yabs : -yabs)) ? y : x;
\r
2050 static half fmax(half x, half y)
\r
2052 int xabs = x.data_ & 0x7FFF, yabs = y.data_ & 0x7FFF;
\r
2057 return (((xabs==x.data_) ? xabs : -xabs) < ((yabs==y.data_) ? yabs : -yabs)) ? y : x;
\r
2061 /// Helper class for half casts.
\r
2062 /// This class template has to be specialized for all valid cast argument to define an appropriate static `cast` member
\r
2063 /// function and a corresponding `type` member denoting its return type.
\r
2064 /// \tparam T destination type
\r
2065 /// \tparam U source type
\r
2066 /// \tparam R rounding mode to use
\r
2067 template<typename T,typename U,std::float_round_style R=(std::float_round_style)(HALF_ROUND_STYLE)> struct half_caster {};
\r
2068 template<typename U,std::float_round_style R> struct half_caster<half,U,R>
\r
2070 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
\r
2071 static_assert(std::is_arithmetic<U>::value, "half_cast from non-arithmetic type unsupported");
\r
2074 static half cast(U arg) { return cast_impl(arg, is_float<U>()); };
\r
2077 static half cast_impl(U arg, true_type) { return half(binary, float2half<R>(arg)); }
\r
2078 static half cast_impl(U arg, false_type) { return half(binary, int2half<R>(arg)); }
\r
2080 template<typename T,std::float_round_style R> struct half_caster<T,half,R>
\r
2082 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
\r
2083 static_assert(std::is_arithmetic<T>::value, "half_cast to non-arithmetic type unsupported");
\r
2086 static T cast(half arg) { return cast_impl(arg, is_float<T>()); }
\r
2089 static T cast_impl(half arg, true_type) { return half2float<T>(arg.data_); }
\r
2090 static T cast_impl(half arg, false_type) { return half2int<R,T>(arg.data_); }
\r
2092 template<typename T,std::float_round_style R> struct half_caster<T,expr,R>
\r
2094 #if HALF_ENABLE_CPP11_STATIC_ASSERT && HALF_ENABLE_CPP11_TYPE_TRAITS
\r
2095 static_assert(std::is_arithmetic<T>::value, "half_cast to non-arithmetic type unsupported");
\r
2098 static T cast(expr arg) { return cast_impl(arg, is_float<T>()); }
\r
2101 static T cast_impl(float arg, true_type) { return static_cast<T>(arg); }
\r
2102 static T cast_impl(half arg, false_type) { return half2int<R,T>(arg.data_); }
\r
2104 template<std::float_round_style R> struct half_caster<half,half,R>
\r
2106 static half cast(half arg) { return arg; }
\r
2108 template<std::float_round_style R> struct half_caster<half,expr,R> : half_caster<half,half,R> {};
\r
2110 /// \name Comparison operators
\r
2113 /// Comparison for equality.
\r
2114 /// \param x first operand
\r
2115 /// \param y second operand
\r
2116 /// \retval true if operands equal
\r
2117 /// \retval false else
\r
2118 template<typename T,typename U> typename enable<bool,T,U>::type operator==(T x, U y) { return functions::isequal(x, y); }
\r
2120 /// Comparison for inequality.
\r
2121 /// \param x first operand
\r
2122 /// \param y second operand
\r
2123 /// \retval true if operands not equal
\r
2124 /// \retval false else
\r
2125 template<typename T,typename U> typename enable<bool,T,U>::type operator!=(T x, U y) { return functions::isnotequal(x, y); }
\r
2127 /// Comparison for less than.
\r
2128 /// \param x first operand
\r
2129 /// \param y second operand
\r
2130 /// \retval true if \a x less than \a y
\r
2131 /// \retval false else
\r
2132 template<typename T,typename U> typename enable<bool,T,U>::type operator<(T x, U y) { return functions::isless(x, y); }
\r
2134 /// Comparison for greater than.
\r
2135 /// \param x first operand
\r
2136 /// \param y second operand
\r
2137 /// \retval true if \a x greater than \a y
\r
2138 /// \retval false else
\r
2139 template<typename T,typename U> typename enable<bool,T,U>::type operator>(T x, U y) { return functions::isgreater(x, y); }
\r
2141 /// Comparison for less equal.
\r
2142 /// \param x first operand
\r
2143 /// \param y second operand
\r
2144 /// \retval true if \a x less equal \a y
\r
2145 /// \retval false else
\r
2146 template<typename T,typename U> typename enable<bool,T,U>::type operator<=(T x, U y) { return functions::islessequal(x, y); }
\r
2148 /// Comparison for greater equal.
\r
2149 /// \param x first operand
\r
2150 /// \param y second operand
\r
2151 /// \retval true if \a x greater equal \a y
\r
2152 /// \retval false else
\r
2153 template<typename T,typename U> typename enable<bool,T,U>::type operator>=(T x, U y) { return functions::isgreaterequal(x, y); }
\r
2156 /// \name Arithmetic operators
\r
2160 /// \param x left operand
\r
2161 /// \param y right operand
\r
2162 /// \return sum of half expressions
\r
2163 template<typename T,typename U> typename enable<expr,T,U>::type operator+(T x, U y) { return functions::plus(x, y); }
\r
2165 /// Subtract halfs.
\r
2166 /// \param x left operand
\r
2167 /// \param y right operand
\r
2168 /// \return difference of half expressions
\r
2169 template<typename T,typename U> typename enable<expr,T,U>::type operator-(T x, U y) { return functions::minus(x, y); }
\r
2171 /// Multiply halfs.
\r
2172 /// \param x left operand
\r
2173 /// \param y right operand
\r
2174 /// \return product of half expressions
\r
2175 template<typename T,typename U> typename enable<expr,T,U>::type operator*(T x, U y) { return functions::multiplies(x, y); }
\r
2178 /// \param x left operand
\r
2179 /// \param y right operand
\r
2180 /// \return quotient of half expressions
\r
2181 template<typename T,typename U> typename enable<expr,T,U>::type operator/(T x, U y) { return functions::divides(x, y); }
\r
2184 /// \param arg operand
\r
2185 /// \return uncahnged operand
\r
2186 template<typename T> HALF_CONSTEXPR typename enable<T,T>::type operator+(T arg) { return arg; }
\r
2189 /// \param arg operand
\r
2190 /// \return negated operand
\r
2191 template<typename T> HALF_CONSTEXPR typename enable<T,T>::type operator-(T arg) { return unary_specialized<T>::negate(arg); }
\r
2194 /// \name Input and output
\r
2197 /// Output operator.
\r
2198 /// \param out output stream to write into
\r
2199 /// \param arg half expression to write
\r
2200 /// \return reference to output stream
\r
2201 template<typename T,typename charT,typename traits> typename enable<std::basic_ostream<charT,traits>&,T>::type
\r
2202 operator<<(std::basic_ostream<charT,traits> &out, T arg) { return functions::write(out, arg); }
\r
2204 /// Input operator.
\r
2205 /// \param in input stream to read from
\r
2206 /// \param arg half to read into
\r
2207 /// \return reference to input stream
\r
2208 template<typename charT,typename traits> std::basic_istream<charT,traits>&
\r
2209 operator>>(std::basic_istream<charT,traits> &in, half &arg) { return functions::read(in, arg); }
\r
2212 /// \name Basic mathematical operations
\r
2215 /// Absolute value.
\r
2216 /// \param arg operand
\r
2217 /// \return absolute value of \a arg
\r
2218 // template<typename T> typename enable<T,T>::type abs(T arg) { return unary_specialized<T>::fabs(arg); }
\r
2219 inline half abs(half arg) { return unary_specialized<half>::fabs(arg); }
\r
2220 inline expr abs(expr arg) { return unary_specialized<expr>::fabs(arg); }
\r
2222 /// Absolute value.
\r
2223 /// \param arg operand
\r
2224 /// \return absolute value of \a arg
\r
2225 // template<typename T> typename enable<T,T>::type fabs(T arg) { return unary_specialized<T>::fabs(arg); }
\r
2226 inline half fabs(half arg) { return unary_specialized<half>::fabs(arg); }
\r
2227 inline expr fabs(expr arg) { return unary_specialized<expr>::fabs(arg); }
\r
2229 /// Remainder of division.
\r
2230 /// \param x first operand
\r
2231 /// \param y second operand
\r
2232 /// \return remainder of floating point division.
\r
2233 // template<typename T,typename U> typename enable<expr,T,U>::type fmod(T x, U y) { return functions::fmod(x, y); }
\r
2234 inline expr fmod(half x, half y) { return functions::fmod(x, y); }
\r
2235 inline expr fmod(half x, expr y) { return functions::fmod(x, y); }
\r
2236 inline expr fmod(expr x, half y) { return functions::fmod(x, y); }
\r
2237 inline expr fmod(expr x, expr y) { return functions::fmod(x, y); }
\r
2239 /// Remainder of division.
\r
2240 /// \param x first operand
\r
2241 /// \param y second operand
\r
2242 /// \return remainder of floating point division.
\r
2243 // template<typename T,typename U> typename enable<expr,T,U>::type remainder(T x, U y) { return functions::remainder(x, y); }
\r
2244 inline expr remainder(half x, half y) { return functions::remainder(x, y); }
\r
2245 inline expr remainder(half x, expr y) { return functions::remainder(x, y); }
\r
2246 inline expr remainder(expr x, half y) { return functions::remainder(x, y); }
\r
2247 inline expr remainder(expr x, expr y) { return functions::remainder(x, y); }
\r
2249 /// Remainder of division.
\r
2250 /// \param x first operand
\r
2251 /// \param y second operand
\r
2252 /// \param quo address to store some bits of quotient at
\r
2253 /// \return remainder of floating point division.
\r
2254 // template<typename T,typename U> typename enable<expr,T,U>::type remquo(T x, U y, int *quo) { return functions::remquo(x, y, quo); }
\r
2255 inline expr remquo(half x, half y, int *quo) { return functions::remquo(x, y, quo); }
\r
2256 inline expr remquo(half x, expr y, int *quo) { return functions::remquo(x, y, quo); }
\r
2257 inline expr remquo(expr x, half y, int *quo) { return functions::remquo(x, y, quo); }
\r
2258 inline expr remquo(expr x, expr y, int *quo) { return functions::remquo(x, y, quo); }
\r
2260 /// Fused multiply add.
\r
2261 /// \param x first operand
\r
2262 /// \param y second operand
\r
2263 /// \param z third operand
\r
2264 /// \return ( \a x * \a y ) + \a z rounded as one operation.
\r
2265 // template<typename T,typename U,typename V> typename enable<expr,T,U,V>::type fma(T x, U y, V z) { return functions::fma(x, y, z); }
\r
2266 inline expr fma(half x, half y, half z) { return functions::fma(x, y, z); }
\r
2267 inline expr fma(half x, half y, expr z) { return functions::fma(x, y, z); }
\r
2268 inline expr fma(half x, expr y, half z) { return functions::fma(x, y, z); }
\r
2269 inline expr fma(half x, expr y, expr z) { return functions::fma(x, y, z); }
\r
2270 inline expr fma(expr x, half y, half z) { return functions::fma(x, y, z); }
\r
2271 inline expr fma(expr x, half y, expr z) { return functions::fma(x, y, z); }
\r
2272 inline expr fma(expr x, expr y, half z) { return functions::fma(x, y, z); }
\r
2273 inline expr fma(expr x, expr y, expr z) { return functions::fma(x, y, z); }
\r
2275 /// Maximum of half expressions.
\r
2276 /// \param x first operand
\r
2277 /// \param y second operand
\r
2278 /// \return maximum of operands
\r
2279 // template<typename T,typename U> typename result<T,U>::type fmax(T x, U y) { return binary_specialized<T,U>::fmax(x, y); }
\r
2280 inline half fmax(half x, half y) { return binary_specialized<half,half>::fmax(x, y); }
\r
2281 inline expr fmax(half x, expr y) { return binary_specialized<half,expr>::fmax(x, y); }
\r
2282 inline expr fmax(expr x, half y) { return binary_specialized<expr,half>::fmax(x, y); }
\r
2283 inline expr fmax(expr x, expr y) { return binary_specialized<expr,expr>::fmax(x, y); }
\r
2285 /// Minimum of half expressions.
\r
2286 /// \param x first operand
\r
2287 /// \param y second operand
\r
2288 /// \return minimum of operands
\r
2289 // template<typename T,typename U> typename result<T,U>::type fmin(T x, U y) { return binary_specialized<T,U>::fmin(x, y); }
\r
2290 inline half fmin(half x, half y) { return binary_specialized<half,half>::fmin(x, y); }
\r
2291 inline expr fmin(half x, expr y) { return binary_specialized<half,expr>::fmin(x, y); }
\r
2292 inline expr fmin(expr x, half y) { return binary_specialized<expr,half>::fmin(x, y); }
\r
2293 inline expr fmin(expr x, expr y) { return binary_specialized<expr,expr>::fmin(x, y); }
\r
2295 /// Positive difference.
\r
2296 /// \param x first operand
\r
2297 /// \param y second operand
\r
2298 /// \return \a x - \a y or 0 if difference negative
\r
2299 // template<typename T,typename U> typename enable<expr,T,U>::type fdim(T x, U y) { return functions::fdim(x, y); }
\r
2300 inline expr fdim(half x, half y) { return functions::fdim(x, y); }
\r
2301 inline expr fdim(half x, expr y) { return functions::fdim(x, y); }
\r
2302 inline expr fdim(expr x, half y) { return functions::fdim(x, y); }
\r
2303 inline expr fdim(expr x, expr y) { return functions::fdim(x, y); }
\r
2305 /// Get NaN value.
\r
2306 /// \return quiet NaN
\r
2307 inline half nanh(const char*) { return functions::nanh(); }
\r
2310 /// \name Exponential functions
\r
2313 /// Exponential function.
\r
2314 /// \param arg function argument
\r
2315 /// \return e raised to \a arg
\r
2316 // template<typename T> typename enable<expr,T>::type exp(T arg) { return functions::exp(arg); }
\r
2317 inline expr exp(half arg) { return functions::exp(arg); }
\r
2318 inline expr exp(expr arg) { return functions::exp(arg); }
\r
2320 /// Exponential minus one.
\r
2321 /// \param arg function argument
\r
2322 /// \return e raised to \a arg subtracted by 1
\r
2323 // template<typename T> typename enable<expr,T>::type expm1(T arg) { return functions::expm1(arg); }
\r
2324 inline expr expm1(half arg) { return functions::expm1(arg); }
\r
2325 inline expr expm1(expr arg) { return functions::expm1(arg); }
\r
2327 /// Binary exponential.
\r
2328 /// \param arg function argument
\r
2329 /// \return 2 raised to \a arg
\r
2330 // template<typename T> typename enable<expr,T>::type exp2(T arg) { return functions::exp2(arg); }
\r
2331 inline expr exp2(half arg) { return functions::exp2(arg); }
\r
2332 inline expr exp2(expr arg) { return functions::exp2(arg); }
\r
2334 /// Natural logorithm.
\r
2335 /// \param arg function argument
\r
2336 /// \return logarithm of \a arg to base e
\r
2337 // template<typename T> typename enable<expr,T>::type log(T arg) { return functions::log(arg); }
\r
2338 inline expr log(half arg) { return functions::log(arg); }
\r
2339 inline expr log(expr arg) { return functions::log(arg); }
\r
2341 /// Common logorithm.
\r
2342 /// \param arg function argument
\r
2343 /// \return logarithm of \a arg to base 10
\r
2344 // template<typename T> typename enable<expr,T>::type log10(T arg) { return functions::log10(arg); }
\r
2345 inline expr log10(half arg) { return functions::log10(arg); }
\r
2346 inline expr log10(expr arg) { return functions::log10(arg); }
\r
2348 /// Natural logorithm.
\r
2349 /// \param arg function argument
\r
2350 /// \return logarithm of \a arg plus 1 to base e
\r
2351 // template<typename T> typename enable<expr,T>::type log1p(T arg) { return functions::log1p(arg); }
\r
2352 inline expr log1p(half arg) { return functions::log1p(arg); }
\r
2353 inline expr log1p(expr arg) { return functions::log1p(arg); }
\r
2355 /// Binary logorithm.
\r
2356 /// \param arg function argument
\r
2357 /// \return logarithm of \a arg to base 2
\r
2358 // template<typename T> typename enable<expr,T>::type log2(T arg) { return functions::log2(arg); }
\r
2359 inline expr log2(half arg) { return functions::log2(arg); }
\r
2360 inline expr log2(expr arg) { return functions::log2(arg); }
\r
2363 /// \name Power functions
\r
2367 /// \param arg function argument
\r
2368 /// \return square root of \a arg
\r
2369 // template<typename T> typename enable<expr,T>::type sqrt(T arg) { return functions::sqrt(arg); }
\r
2370 inline expr sqrt(half arg) { return functions::sqrt(arg); }
\r
2371 inline expr sqrt(expr arg) { return functions::sqrt(arg); }
\r
2374 /// \param arg function argument
\r
2375 /// \return cubic root of \a arg
\r
2376 // template<typename T> typename enable<expr,T>::type cbrt(T arg) { return functions::cbrt(arg); }
\r
2377 inline expr cbrt(half arg) { return functions::cbrt(arg); }
\r
2378 inline expr cbrt(expr arg) { return functions::cbrt(arg); }
\r
2380 /// Hypotenuse function.
\r
2381 /// \param x first argument
\r
2382 /// \param y second argument
\r
2383 /// \return square root of sum of squares without internal over- or underflows
\r
2384 // template<typename T,typename U> typename enable<expr,T,U>::type hypot(T x, U y) { return functions::hypot(x, y); }
\r
2385 inline expr hypot(half x, half y) { return functions::hypot(x, y); }
\r
2386 inline expr hypot(half x, expr y) { return functions::hypot(x, y); }
\r
2387 inline expr hypot(expr x, half y) { return functions::hypot(x, y); }
\r
2388 inline expr hypot(expr x, expr y) { return functions::hypot(x, y); }
\r
2390 /// Power function.
\r
2391 /// \param base first argument
\r
2392 /// \param exp second argument
\r
2393 /// \return \a base raised to \a exp
\r
2394 // template<typename T,typename U> typename enable<expr,T,U>::type pow(T base, U exp) { return functions::pow(base, exp); }
\r
2395 inline expr pow(half base, half exp) { return functions::pow(base, exp); }
\r
2396 inline expr pow(half base, expr exp) { return functions::pow(base, exp); }
\r
2397 inline expr pow(expr base, half exp) { return functions::pow(base, exp); }
\r
2398 inline expr pow(expr base, expr exp) { return functions::pow(base, exp); }
\r
2401 /// \name Trigonometric functions
\r
2404 /// Sine function.
\r
2405 /// \param arg function argument
\r
2406 /// \return sine value of \a arg
\r
2407 // template<typename T> typename enable<expr,T>::type sin(T arg) { return functions::sin(arg); }
\r
2408 inline expr sin(half arg) { return functions::sin(arg); }
\r
2409 inline expr sin(expr arg) { return functions::sin(arg); }
\r
2411 /// Cosine function.
\r
2412 /// \param arg function argument
\r
2413 /// \return cosine value of \a arg
\r
2414 // template<typename T> typename enable<expr,T>::type cos(T arg) { return functions::cos(arg); }
\r
2415 inline expr cos(half arg) { return functions::cos(arg); }
\r
2416 inline expr cos(expr arg) { return functions::cos(arg); }
\r
2418 /// Tangent function.
\r
2419 /// \param arg function argument
\r
2420 /// \return tangent value of \a arg
\r
2421 // template<typename T> typename enable<expr,T>::type tan(T arg) { return functions::tan(arg); }
\r
2422 inline expr tan(half arg) { return functions::tan(arg); }
\r
2423 inline expr tan(expr arg) { return functions::tan(arg); }
\r
2426 /// \param arg function argument
\r
2427 /// \return arc sine value of \a arg
\r
2428 // template<typename T> typename enable<expr,T>::type asin(T arg) { return functions::asin(arg); }
\r
2429 inline expr asin(half arg) { return functions::asin(arg); }
\r
2430 inline expr asin(expr arg) { return functions::asin(arg); }
\r
2432 /// Arc cosine function.
\r
2433 /// \param arg function argument
\r
2434 /// \return arc cosine value of \a arg
\r
2435 // template<typename T> typename enable<expr,T>::type acos(T arg) { return functions::acos(arg); }
\r
2436 inline expr acos(half arg) { return functions::acos(arg); }
\r
2437 inline expr acos(expr arg) { return functions::acos(arg); }
\r
2439 /// Arc tangent function.
\r
2440 /// \param arg function argument
\r
2441 /// \return arc tangent value of \a arg
\r
2442 // template<typename T> typename enable<expr,T>::type atan(T arg) { return functions::atan(arg); }
\r
2443 inline expr atan(half arg) { return functions::atan(arg); }
\r
2444 inline expr atan(expr arg) { return functions::atan(arg); }
\r
2446 /// Arc tangent function.
\r
2447 /// \param x first argument
\r
2448 /// \param y second argument
\r
2449 /// \return arc tangent value
\r
2450 // template<typename T,typename U> typename enable<expr,T,U>::type atan2(T x, U y) { return functions::atan2(x, y); }
\r
2451 inline expr atan2(half x, half y) { return functions::atan2(x, y); }
\r
2452 inline expr atan2(half x, expr y) { return functions::atan2(x, y); }
\r
2453 inline expr atan2(expr x, half y) { return functions::atan2(x, y); }
\r
2454 inline expr atan2(expr x, expr y) { return functions::atan2(x, y); }
\r
2457 /// \name Hyperbolic functions
\r
2460 /// Hyperbolic sine.
\r
2461 /// \param arg function argument
\r
2462 /// \return hyperbolic sine value of \a arg
\r
2463 // template<typename T> typename enable<expr,T>::type sinh(T arg) { return functions::sinh(arg); }
\r
2464 inline expr sinh(half arg) { return functions::sinh(arg); }
\r
2465 inline expr sinh(expr arg) { return functions::sinh(arg); }
\r
2467 /// Hyperbolic cosine.
\r
2468 /// \param arg function argument
\r
2469 /// \return hyperbolic cosine value of \a arg
\r
2470 // template<typename T> typename enable<expr,T>::type cosh(T arg) { return functions::cosh(arg); }
\r
2471 inline expr cosh(half arg) { return functions::cosh(arg); }
\r
2472 inline expr cosh(expr arg) { return functions::cosh(arg); }
\r
2474 /// Hyperbolic tangent.
\r
2475 /// \param arg function argument
\r
2476 /// \return hyperbolic tangent value of \a arg
\r
2477 // template<typename T> typename enable<expr,T>::type tanh(T arg) { return functions::tanh(arg); }
\r
2478 inline expr tanh(half arg) { return functions::tanh(arg); }
\r
2479 inline expr tanh(expr arg) { return functions::tanh(arg); }
\r
2481 /// Hyperbolic area sine.
\r
2482 /// \param arg function argument
\r
2483 /// \return area sine value of \a arg
\r
2484 // template<typename T> typename enable<expr,T>::type asinh(T arg) { return functions::asinh(arg); }
\r
2485 inline expr asinh(half arg) { return functions::asinh(arg); }
\r
2486 inline expr asinh(expr arg) { return functions::asinh(arg); }
\r
2488 /// Hyperbolic area cosine.
\r
2489 /// \param arg function argument
\r
2490 /// \return area cosine value of \a arg
\r
2491 // template<typename T> typename enable<expr,T>::type acosh(T arg) { return functions::acosh(arg); }
\r
2492 inline expr acosh(half arg) { return functions::acosh(arg); }
\r
2493 inline expr acosh(expr arg) { return functions::acosh(arg); }
\r
2495 /// Hyperbolic area tangent.
\r
2496 /// \param arg function argument
\r
2497 /// \return area tangent value of \a arg
\r
2498 // template<typename T> typename enable<expr,T>::type atanh(T arg) { return functions::atanh(arg); }
\r
2499 inline expr atanh(half arg) { return functions::atanh(arg); }
\r
2500 inline expr atanh(expr arg) { return functions::atanh(arg); }
\r
2503 /// \name Error and gamma functions
\r
2506 /// Error function.
\r
2507 /// \param arg function argument
\r
2508 /// \return error function value of \a arg
\r
2509 // template<typename T> typename enable<expr,T>::type erf(T arg) { return functions::erf(arg); }
\r
2510 inline expr erf(half arg) { return functions::erf(arg); }
\r
2511 inline expr erf(expr arg) { return functions::erf(arg); }
\r
2513 /// Complementary error function.
\r
2514 /// \param arg function argument
\r
2515 /// \return 1 minus error function value of \a arg
\r
2516 // template<typename T> typename enable<expr,T>::type erfc(T arg) { return functions::erfc(arg); }
\r
2517 inline expr erfc(half arg) { return functions::erfc(arg); }
\r
2518 inline expr erfc(expr arg) { return functions::erfc(arg); }
\r
2520 /// Natural logarithm of gamma function.
\r
2521 /// \param arg function argument
\r
2522 /// \return natural logarith of gamma function for \a arg
\r
2523 // template<typename T> typename enable<expr,T>::type lgamma(T arg) { return functions::lgamma(arg); }
\r
2524 inline expr lgamma(half arg) { return functions::lgamma(arg); }
\r
2525 inline expr lgamma(expr arg) { return functions::lgamma(arg); }
\r
2527 /// Gamma function.
\r
2528 /// \param arg function argument
\r
2529 /// \return gamma function value of \a arg
\r
2530 // template<typename T> typename enable<expr,T>::type tgamma(T arg) { return functions::tgamma(arg); }
\r
2531 inline expr tgamma(half arg) { return functions::tgamma(arg); }
\r
2532 inline expr tgamma(expr arg) { return functions::tgamma(arg); }
\r
2535 /// \name Rounding
\r
2538 /// Nearest integer not less than half value.
\r
2539 /// \param arg half to round
\r
2540 /// \return nearest integer not less than \a arg
\r
2541 // template<typename T> typename enable<half,T>::type ceil(T arg) { return functions::ceil(arg); }
\r
2542 inline half ceil(half arg) { return functions::ceil(arg); }
\r
2543 inline half ceil(expr arg) { return functions::ceil(arg); }
\r
2545 /// Nearest integer not greater than half value.
\r
2546 /// \param arg half to round
\r
2547 /// \return nearest integer not greater than \a arg
\r
2548 // template<typename T> typename enable<half,T>::type floor(T arg) { return functions::floor(arg); }
\r
2549 inline half floor(half arg) { return functions::floor(arg); }
\r
2550 inline half floor(expr arg) { return functions::floor(arg); }
\r
2552 /// Nearest integer not greater in magnitude than half value.
\r
2553 /// \param arg half to round
\r
2554 /// \return nearest integer not greater in magnitude than \a arg
\r
2555 // template<typename T> typename enable<half,T>::type trunc(T arg) { return functions::trunc(arg); }
\r
2556 inline half trunc(half arg) { return functions::trunc(arg); }
\r
2557 inline half trunc(expr arg) { return functions::trunc(arg); }
\r
2559 /// Nearest integer.
\r
2560 /// \param arg half to round
\r
2561 /// \return nearest integer, rounded away from zero in half-way cases
\r
2562 // template<typename T> typename enable<half,T>::type round(T arg) { return functions::round(arg); }
\r
2563 inline half round(half arg) { return functions::round(arg); }
\r
2564 inline half round(expr arg) { return functions::round(arg); }
\r
2566 /// Nearest integer.
\r
2567 /// \param arg half to round
\r
2568 /// \return nearest integer, rounded away from zero in half-way cases
\r
2569 // template<typename T> typename enable<long,T>::type lround(T arg) { return functions::lround(arg); }
\r
2570 inline long lround(half arg) { return functions::lround(arg); }
\r
2571 inline long lround(expr arg) { return functions::lround(arg); }
\r
2573 /// Nearest integer using half's internal rounding mode.
\r
2574 /// \param arg half expression to round
\r
2575 /// \return nearest integer using default rounding mode
\r
2576 // template<typename T> typename enable<half,T>::type nearbyint(T arg) { return functions::nearbyint(arg); }
\r
2577 inline half nearbyint(half arg) { return functions::rint(arg); }
\r
2578 inline half nearbyint(expr arg) { return functions::rint(arg); }
\r
2580 /// Nearest integer using half's internal rounding mode.
\r
2581 /// \param arg half expression to round
\r
2582 /// \return nearest integer using default rounding mode
\r
2583 // template<typename T> typename enable<half,T>::type rint(T arg) { return functions::rint(arg); }
\r
2584 inline half rint(half arg) { return functions::rint(arg); }
\r
2585 inline half rint(expr arg) { return functions::rint(arg); }
\r
2587 /// Nearest integer using half's internal rounding mode.
\r
2588 /// \param arg half expression to round
\r
2589 /// \return nearest integer using default rounding mode
\r
2590 // template<typename T> typename enable<long,T>::type lrint(T arg) { return functions::lrint(arg); }
\r
2591 inline long lrint(half arg) { return functions::lrint(arg); }
\r
2592 inline long lrint(expr arg) { return functions::lrint(arg); }
\r
2593 #if HALF_ENABLE_CPP11_LONG_LONG
\r
2594 /// Nearest integer.
\r
2595 /// \param arg half to round
\r
2596 /// \return nearest integer, rounded away from zero in half-way cases
\r
2597 // template<typename T> typename enable<long long,T>::type llround(T arg) { return functions::llround(arg); }
\r
2598 inline long long llround(half arg) { return functions::llround(arg); }
\r
2599 inline long long llround(expr arg) { return functions::llround(arg); }
\r
2601 /// Nearest integer using half's internal rounding mode.
\r
2602 /// \param arg half expression to round
\r
2603 /// \return nearest integer using default rounding mode
\r
2604 // template<typename T> typename enable<long long,T>::type llrint(T arg) { return functions::llrint(arg); }
\r
2605 inline long long llrint(half arg) { return functions::llrint(arg); }
\r
2606 inline long long llrint(expr arg) { return functions::llrint(arg); }
\r
2610 /// \name Floating point manipulation
\r
2613 /// Decompress floating point number.
\r
2614 /// \param arg number to decompress
\r
2615 /// \param exp address to store exponent at
\r
2616 /// \return significant in range [0.5, 1)
\r
2617 // template<typename T> typename enable<half,T>::type frexp(T arg, int *exp) { return functions::frexp(arg, exp); }
\r
2618 inline half frexp(half arg, int *exp) { return functions::frexp(arg, exp); }
\r
2619 inline half frexp(expr arg, int *exp) { return functions::frexp(arg, exp); }
\r
2621 /// Multiply by power of two.
\r
2622 /// \param arg number to modify
\r
2623 /// \param exp power of two to multiply with
\r
2624 /// \return \a arg multplied by 2 raised to \a exp
\r
2625 // template<typename T> typename enable<half,T>::type ldexp(T arg, int exp) { return functions::scalbln(arg, exp); }
\r
2626 inline half ldexp(half arg, int exp) { return functions::scalbln(arg, exp); }
\r
2627 inline half ldexp(expr arg, int exp) { return functions::scalbln(arg, exp); }
\r
2629 /// Extract integer and fractional parts.
\r
2630 /// \param arg number to decompress
\r
2631 /// \param iptr address to store integer part at
\r
2632 /// \return fractional part
\r
2633 // template<typename T> typename enable<half,T>::type modf(T arg, half *iptr) { return functions::modf(arg, iptr); }
\r
2634 inline half modf(half arg, half *iptr) { return functions::modf(arg, iptr); }
\r
2635 inline half modf(expr arg, half *iptr) { return functions::modf(arg, iptr); }
\r
2637 /// Multiply by power of two.
\r
2638 /// \param arg number to modify
\r
2639 /// \param exp power of two to multiply with
\r
2640 /// \return \a arg multplied by 2 raised to \a exp
\r
2641 // template<typename T> typename enable<half,T>::type scalbn(T arg, int exp) { return functions::scalbln(arg, exp); }
\r
2642 inline half scalbn(half arg, int exp) { return functions::scalbln(arg, exp); }
\r
2643 inline half scalbn(expr arg, int exp) { return functions::scalbln(arg, exp); }
\r
2645 /// Multiply by power of two.
\r
2646 /// \param arg number to modify
\r
2647 /// \param exp power of two to multiply with
\r
2648 /// \return \a arg multplied by 2 raised to \a exp
\r
2649 // template<typename T> typename enable<half,T>::type scalbln(T arg, long exp) { return functions::scalbln(arg, exp); }
\r
2650 inline half scalbln(half arg, long exp) { return functions::scalbln(arg, exp); }
\r
2651 inline half scalbln(expr arg, long exp) { return functions::scalbln(arg, exp); }
\r
2653 /// Extract exponent.
\r
2654 /// \param arg number to query
\r
2655 /// \return floating point exponent
\r
2656 /// \retval FP_ILOGB0 for zero
\r
2657 /// \retval FP_ILOGBNAN for NaN
\r
2658 /// \retval MAX_INT for infinity
\r
2659 // template<typename T> typename enable<int,T>::type ilogb(T arg) { return functions::ilogb(arg); }
\r
2660 inline int ilogb(half arg) { return functions::ilogb(arg); }
\r
2661 inline int ilogb(expr arg) { return functions::ilogb(arg); }
\r
2663 /// Extract exponent.
\r
2664 /// \param arg number to query
\r
2665 /// \return floating point exponent
\r
2666 // template<typename T> typename enable<half,T>::type logb(T arg) { return functions::logb(arg); }
\r
2667 inline half logb(half arg) { return functions::logb(arg); }
\r
2668 inline half logb(expr arg) { return functions::logb(arg); }
\r
2670 /// Next representable value.
\r
2671 /// \param from value to compute next representable value for
\r
2672 /// \param to direction towards which to compute next value
\r
2673 /// \return next representable value after \a from in direction towards \a to
\r
2674 // template<typename T,typename U> typename enable<half,T,U>::type nextafter(T from, U to) { return functions::nextafter(from, to); }
\r
2675 inline half nextafter(half from, half to) { return functions::nextafter(from, to); }
\r
2676 inline half nextafter(half from, expr to) { return functions::nextafter(from, to); }
\r
2677 inline half nextafter(expr from, half to) { return functions::nextafter(from, to); }
\r
2678 inline half nextafter(expr from, expr to) { return functions::nextafter(from, to); }
\r
2680 /// Next representable value.
\r
2681 /// \param from value to compute next representable value for
\r
2682 /// \param to direction towards which to compute next value
\r
2683 /// \return next representable value after \a from in direction towards \a to
\r
2684 // template<typename T> typename enable<half,T>::type nexttoward(T from, long double to) { return functions::nexttoward(from, to); }
\r
2685 inline half nexttoward(half from, long double to) { return functions::nexttoward(from, to); }
\r
2686 inline half nexttoward(expr from, long double to) { return functions::nexttoward(from, to); }
\r
2689 /// \param x value to change sign for
\r
2690 /// \param y value to take sign from
\r
2691 /// \return value equal to \a x in magnitude and to \a y in sign
\r
2692 // template<typename T,typename U> typename enable<half,T,U>::type copysign(T x, U y) { return functions::copysign(x, y); }
\r
2693 inline half copysign(half x, half y) { return functions::copysign(x, y); }
\r
2694 inline half copysign(half x, expr y) { return functions::copysign(x, y); }
\r
2695 inline half copysign(expr x, half y) { return functions::copysign(x, y); }
\r
2696 inline half copysign(expr x, expr y) { return functions::copysign(x, y); }
\r
2699 /// \name Floating point classification
\r
2703 /// Classify floating point value.
\r
2704 /// \param arg number to classify
\r
2705 /// \retval FP_ZERO for positive and negative zero
\r
2706 /// \retval FP_SUBNORMAL for subnormal numbers
\r
2707 /// \retval FP_INFINITY for positive and negative infinity
\r
2708 /// \retval FP_NAN for NaNs
\r
2709 /// \retval FP_NORMAL for all other (normal) values
\r
2710 // template<typename T> typename enable<int,T>::type fpclassify(T arg) { return functions::fpclassify(arg); }
\r
2711 inline int fpclassify(half arg) { return functions::fpclassify(arg); }
\r
2712 inline int fpclassify(expr arg) { return functions::fpclassify(arg); }
\r
2714 /// Check if finite number.
\r
2715 /// \param arg number to check
\r
2716 /// \retval true if neither infinity nor NaN
\r
2717 /// \retval false else
\r
2718 // template<typename T> typename enable<bool,T>::type isfinite(T arg) { return functions::isfinite(arg); }
\r
2719 inline bool isfinite(half arg) { return functions::isfinite(arg); }
\r
2720 inline bool isfinite(expr arg) { return functions::isfinite(arg); }
\r
2722 /// Check for infinity.
\r
2723 /// \param arg number to check
\r
2724 /// \retval true for positive or negative infinity
\r
2725 /// \retval false else
\r
2726 // template<typename T> typename enable<bool,T>::type isinf(T arg) { return functions::isinf(arg); }
\r
2727 inline bool isinf(half arg) { return functions::isinf(arg); }
\r
2728 inline bool isinf(expr arg) { return functions::isinf(arg); }
\r
2730 /// Check for NaN.
\r
2731 /// \param arg number to check
\r
2732 /// \retval true for NaNs
\r
2733 /// \retval false else
\r
2734 // template<typename T> typename enable<bool,T>::type isnan(T arg) { return functions::isnan(arg); }
\r
2735 inline bool isnan(half arg) { return functions::isnan(arg); }
\r
2736 inline bool isnan(expr arg) { return functions::isnan(arg); }
\r
2738 /// Check if normal number.
\r
2739 /// \param arg number to check
\r
2740 /// \retval true if normal number
\r
2741 /// \retval false if either subnormal, zero, infinity or NaN
\r
2742 // template<typename T> typename enable<bool,T>::type isnormal(T arg) { return functions::isnormal(arg); }
\r
2743 inline bool isnormal(half arg) { return functions::isnormal(arg); }
\r
2744 inline bool isnormal(expr arg) { return functions::isnormal(arg); }
\r
2747 /// \param arg number to check
\r
2748 /// \retval true for negative number
\r
2749 /// \retval false for positive number
\r
2750 // template<typename T> typename enable<bool,T>::type signbit(T arg) { return functions::signbit(arg); }
\r
2751 inline bool signbit(half arg) { return functions::signbit(arg); }
\r
2752 inline bool signbit(expr arg) { return functions::signbit(arg); }
\r
2755 /// \name Comparison
\r
2758 /// Comparison for greater than.
\r
2759 /// \param x first operand
\r
2760 /// \param y second operand
\r
2761 /// \retval true if \a x greater than \a y
\r
2762 /// \retval false else
\r
2763 // template<typename T,typename U> typename enable<bool,T,U>::type isgreater(T x, U y) { return functions::isgreater(x, y); }
\r
2764 inline bool isgreater(half x, half y) { return functions::isgreater(x, y); }
\r
2765 inline bool isgreater(half x, expr y) { return functions::isgreater(x, y); }
\r
2766 inline bool isgreater(expr x, half y) { return functions::isgreater(x, y); }
\r
2767 inline bool isgreater(expr x, expr y) { return functions::isgreater(x, y); }
\r
2769 /// Comparison for greater equal.
\r
2770 /// \param x first operand
\r
2771 /// \param y second operand
\r
2772 /// \retval true if \a x greater equal \a y
\r
2773 /// \retval false else
\r
2774 // template<typename T,typename U> typename enable<bool,T,U>::type isgreaterequal(T x, U y) { return functions::isgreaterequal(x, y); }
\r
2775 inline bool isgreaterequal(half x, half y) { return functions::isgreaterequal(x, y); }
\r
2776 inline bool isgreaterequal(half x, expr y) { return functions::isgreaterequal(x, y); }
\r
2777 inline bool isgreaterequal(expr x, half y) { return functions::isgreaterequal(x, y); }
\r
2778 inline bool isgreaterequal(expr x, expr y) { return functions::isgreaterequal(x, y); }
\r
2780 /// Comparison for less than.
\r
2781 /// \param x first operand
\r
2782 /// \param y second operand
\r
2783 /// \retval true if \a x less than \a y
\r
2784 /// \retval false else
\r
2785 // template<typename T,typename U> typename enable<bool,T,U>::type isless(T x, U y) { return functions::isless(x, y); }
\r
2786 inline bool isless(half x, half y) { return functions::isless(x, y); }
\r
2787 inline bool isless(half x, expr y) { return functions::isless(x, y); }
\r
2788 inline bool isless(expr x, half y) { return functions::isless(x, y); }
\r
2789 inline bool isless(expr x, expr y) { return functions::isless(x, y); }
\r
2791 /// Comparison for less equal.
\r
2792 /// \param x first operand
\r
2793 /// \param y second operand
\r
2794 /// \retval true if \a x less equal \a y
\r
2795 /// \retval false else
\r
2796 // template<typename T,typename U> typename enable<bool,T,U>::type islessequal(T x, U y) { return functions::islessequal(x, y); }
\r
2797 inline bool islessequal(half x, half y) { return functions::islessequal(x, y); }
\r
2798 inline bool islessequal(half x, expr y) { return functions::islessequal(x, y); }
\r
2799 inline bool islessequal(expr x, half y) { return functions::islessequal(x, y); }
\r
2800 inline bool islessequal(expr x, expr y) { return functions::islessequal(x, y); }
\r
2802 /// Comarison for less or greater.
\r
2803 /// \param x first operand
\r
2804 /// \param y second operand
\r
2805 /// \retval true if either less or greater
\r
2806 /// \retval false else
\r
2807 // template<typename T,typename U> typename enable<bool,T,U>::type islessgreater(T x, U y) { return functions::islessgreater(x, y); }
\r
2808 inline bool islessgreater(half x, half y) { return functions::islessgreater(x, y); }
\r
2809 inline bool islessgreater(half x, expr y) { return functions::islessgreater(x, y); }
\r
2810 inline bool islessgreater(expr x, half y) { return functions::islessgreater(x, y); }
\r
2811 inline bool islessgreater(expr x, expr y) { return functions::islessgreater(x, y); }
\r
2813 /// Check if unordered.
\r
2814 /// \param x first operand
\r
2815 /// \param y second operand
\r
2816 /// \retval true if unordered (one or two NaN operands)
\r
2817 /// \retval false else
\r
2818 // template<typename T,typename U> typename enable<bool,T,U>::type isunordered(T x, U y) { return functions::isunordered(x, y); }
\r
2819 inline bool isunordered(half x, half y) { return functions::isunordered(x, y); }
\r
2820 inline bool isunordered(half x, expr y) { return functions::isunordered(x, y); }
\r
2821 inline bool isunordered(expr x, half y) { return functions::isunordered(x, y); }
\r
2822 inline bool isunordered(expr x, expr y) { return functions::isunordered(x, y); }
\r
2827 /// Cast to or from half-precision floating point number.
\r
2828 /// This casts between [half](\ref half_float::half) and any built-in arithmetic type. The values are converted
\r
2829 /// directly using the given rounding mode, without any roundtrip over `float` that a `static_cast` would otherwise do.
\r
2830 /// It uses the default rounding mode.
\r
2832 /// Using this cast with neither of the two types being a [half](\ref half_float::half) or with any of the two types
\r
2833 /// not being a built-in arithmetic type (apart from [half](\ref half_float::half), of course) results in a compiler
\r
2834 /// error and casting between [half](\ref half_float::half)s is just a no-op.
\r
2835 /// \tparam T destination type (half or built-in arithmetic type)
\r
2836 /// \tparam U source type (half or built-in arithmetic type)
\r
2837 /// \param arg value to cast
\r
2838 /// \return \a arg converted to destination type
\r
2839 template<typename T,typename U> T half_cast(U arg) { return half_caster<T,U>::cast(arg); }
\r
2841 /// Cast to or from half-precision floating point number.
\r
2842 /// This casts between [half](\ref half_float::half) and any built-in arithmetic type. The values are converted
\r
2843 /// directly using the given rounding mode, without any roundtrip over `float` that a `static_cast` would otherwise do.
\r
2845 /// Using this cast with neither of the two types being a [half](\ref half_float::half) or with any of the two types
\r
2846 /// not being a built-in arithmetic type (apart from [half](\ref half_float::half), of course) results in a compiler
\r
2847 /// error and casting between [half](\ref half_float::half)s is just a no-op.
\r
2848 /// \tparam T destination type (half or built-in arithmetic type)
\r
2849 /// \tparam R rounding mode to use.
\r
2850 /// \tparam U source type (half or built-in arithmetic type)
\r
2851 /// \param arg value to cast
\r
2852 /// \return \a arg converted to destination type
\r
2853 template<typename T,std::float_round_style R,typename U> T half_cast(U arg) { return half_caster<T,U,R>::cast(arg); }
\r
2857 using detail::operator==;
\r
2858 using detail::operator!=;
\r
2859 using detail::operator<;
\r
2860 using detail::operator>;
\r
2861 using detail::operator<=;
\r
2862 using detail::operator>=;
\r
2863 using detail::operator+;
\r
2864 using detail::operator-;
\r
2865 using detail::operator*;
\r
2866 using detail::operator/;
\r
2867 using detail::operator<<;
\r
2868 using detail::operator>>;
\r
2870 using detail::abs;
\r
2871 using detail::fabs;
\r
2872 using detail::fmod;
\r
2873 using detail::remainder;
\r
2874 using detail::remquo;
\r
2875 using detail::fma;
\r
2876 using detail::fmax;
\r
2877 using detail::fmin;
\r
2878 using detail::fdim;
\r
2879 using detail::nanh;
\r
2880 using detail::exp;
\r
2881 using detail::expm1;
\r
2882 using detail::exp2;
\r
2883 using detail::log;
\r
2884 using detail::log10;
\r
2885 using detail::log1p;
\r
2886 using detail::log2;
\r
2887 using detail::sqrt;
\r
2888 using detail::cbrt;
\r
2889 using detail::hypot;
\r
2890 using detail::pow;
\r
2891 using detail::sin;
\r
2892 using detail::cos;
\r
2893 using detail::tan;
\r
2894 using detail::asin;
\r
2895 using detail::acos;
\r
2896 using detail::atan;
\r
2897 using detail::atan2;
\r
2898 using detail::sinh;
\r
2899 using detail::cosh;
\r
2900 using detail::tanh;
\r
2901 using detail::asinh;
\r
2902 using detail::acosh;
\r
2903 using detail::atanh;
\r
2904 using detail::erf;
\r
2905 using detail::erfc;
\r
2906 using detail::lgamma;
\r
2907 using detail::tgamma;
\r
2908 using detail::ceil;
\r
2909 using detail::floor;
\r
2910 using detail::trunc;
\r
2911 using detail::round;
\r
2912 using detail::lround;
\r
2913 using detail::nearbyint;
\r
2914 using detail::rint;
\r
2915 using detail::lrint;
\r
2916 #if HALF_ENABLE_CPP11_LONG_LONG
\r
2917 using detail::llround;
\r
2918 using detail::llrint;
\r
2920 using detail::frexp;
\r
2921 using detail::ldexp;
\r
2922 using detail::modf;
\r
2923 using detail::scalbn;
\r
2924 using detail::scalbln;
\r
2925 using detail::ilogb;
\r
2926 using detail::logb;
\r
2927 using detail::nextafter;
\r
2928 using detail::nexttoward;
\r
2929 using detail::copysign;
\r
2930 using detail::fpclassify;
\r
2931 using detail::isfinite;
\r
2932 using detail::isinf;
\r
2933 using detail::isnan;
\r
2934 using detail::isnormal;
\r
2935 using detail::signbit;
\r
2936 using detail::isgreater;
\r
2937 using detail::isgreaterequal;
\r
2938 using detail::isless;
\r
2939 using detail::islessequal;
\r
2940 using detail::islessgreater;
\r
2941 using detail::isunordered;
\r
2943 using detail::half_cast;
\r
2947 /// Extensions to the C++ standard library.
\r
2950 /// Numeric limits for half-precision floats.
\r
2951 /// Because of the underlying single-precision implementation of many operations, it inherits some properties from
\r
2952 /// `std::numeric_limits<float>`.
\r
2953 template<> class numeric_limits<half_float::half> : public numeric_limits<float>
\r
2956 /// Supports signed values.
\r
2957 static HALF_CONSTEXPR_CONST bool is_signed = true;
\r
2960 static HALF_CONSTEXPR_CONST bool is_exact = false;
\r
2962 /// Doesn't provide modulo arithmetic.
\r
2963 static HALF_CONSTEXPR_CONST bool is_modulo = false;
\r
2965 /// IEEE conformant.
\r
2966 static HALF_CONSTEXPR_CONST bool is_iec559 = true;
\r
2968 /// Supports infinity.
\r
2969 static HALF_CONSTEXPR_CONST bool has_infinity = true;
\r
2971 /// Supports quiet NaNs.
\r
2972 static HALF_CONSTEXPR_CONST bool has_quiet_NaN = true;
\r
2974 /// Supports subnormal values.
\r
2975 static HALF_CONSTEXPR_CONST float_denorm_style has_denorm = denorm_present;
\r
2977 /// Rounding mode.
\r
2978 /// Due to the mix of internal single-precision computations (using the rounding mode of the underlying
\r
2979 /// single-precision implementation) with the rounding mode of the single-to-half conversions, the actual rounding
\r
2980 /// mode might be `std::round_indeterminate` if the default half-precision rounding mode doesn't match the
\r
2981 /// single-precision rounding mode.
\r
2982 static HALF_CONSTEXPR_CONST float_round_style round_style = (std::numeric_limits<float>::round_style==
\r
2983 half_float::half::round_style) ? half_float::half::round_style : round_indeterminate;
\r
2985 /// Significant digits.
\r
2986 static HALF_CONSTEXPR_CONST int digits = 11;
\r
2988 /// Significant decimal digits.
\r
2989 static HALF_CONSTEXPR_CONST int digits10 = 3;
\r
2991 /// Required decimal digits to represent all possible values.
\r
2992 static HALF_CONSTEXPR_CONST int max_digits10 = 5;
\r
2995 static HALF_CONSTEXPR_CONST int radix = 2;
\r
2997 /// One more than smallest exponent.
\r
2998 static HALF_CONSTEXPR_CONST int min_exponent = -13;
\r
3000 /// Smallest normalized representable power of 10.
\r
3001 static HALF_CONSTEXPR_CONST int min_exponent10 = -4;
\r
3003 /// One more than largest exponent
\r
3004 static HALF_CONSTEXPR_CONST int max_exponent = 16;
\r
3006 /// Largest finitely representable power of 10.
\r
3007 static HALF_CONSTEXPR_CONST int max_exponent10 = 4;
\r
3009 /// Smallest positive normal value.
\r
3010 static HALF_CONSTEXPR half_float::half min() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x0400); }
\r
3012 /// Smallest finite value.
\r
3013 static HALF_CONSTEXPR half_float::half lowest() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0xFBFF); }
\r
3015 /// Largest finite value.
\r
3016 static HALF_CONSTEXPR half_float::half max() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x7BFF); }
\r
3018 /// Difference between one and next representable value.
\r
3019 static HALF_CONSTEXPR half_float::half epsilon() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x1400); }
\r
3021 /// Maximum rounding error.
\r
3022 static HALF_CONSTEXPR half_float::half round_error() HALF_NOTHROW
\r
3023 { return half_float::half(half_float::detail::binary, (round_style==std::round_to_nearest) ? 0x3800 : 0x3C00); }
\r
3025 /// Positive infinity.
\r
3026 static HALF_CONSTEXPR half_float::half infinity() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x7C00); }
\r
3029 static HALF_CONSTEXPR half_float::half quiet_NaN() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x7FFF); }
\r
3031 /// Signalling NaN.
\r
3032 static HALF_CONSTEXPR half_float::half signaling_NaN() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x7DFF); }
\r
3034 /// Smallest positive subnormal value.
\r
3035 static HALF_CONSTEXPR half_float::half denorm_min() HALF_NOTHROW { return half_float::half(half_float::detail::binary, 0x0001); }
\r
3038 #if HALF_ENABLE_CPP11_HASH
\r
3039 /// Hash function for half-precision floats.
\r
3040 /// This is only defined if C++11 `std::hash` is supported and enabled.
\r
3041 template<> struct hash<half_float::half> //: unary_function<half_float::half,size_t>
\r
3043 /// Type of function argument.
\r
3044 typedef half_float::half argument_type;
\r
3046 /// Function return type.
\r
3047 typedef size_t result_type;
\r
3049 /// Compute hash function.
\r
3050 /// \param arg half to hash
\r
3051 /// \return hash value
\r
3052 result_type operator()(argument_type arg) const
\r
3053 { return hash<half_float::detail::uint16>()(static_cast<unsigned>(arg.data_)&-(arg.data_!=0x8000)); }
\r
3059 #undef HALF_CONSTEXPR
\r
3060 #undef HALF_CONSTEXPR_CONST
\r
3061 #undef HALF_NOEXCEPT
\r
3062 #undef HALF_NOTHROW
\r
3063 #ifdef HALF_POP_WARNINGS
\r
3064 #pragma warning(pop)
\r
3065 #undef HALF_POP_WARNINGS
\r