xref: /aosp_15_r20/external/ComputeLibrary/include/half/half.hpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
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