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