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