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