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