Pack required boost code together.
[xy_vsfilter.git] / src / thirdparty / boost_1_47_0 / boost / functional / hash / detail / float_functions.hpp
blobde91fc202e85b2d30d2ba80059d9299881f68ee6
2 // Copyright 2005-2009 Daniel James.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP)
7 #define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP
9 #include <boost/config.hpp>
10 #include <boost/config/no_tr1/cmath.hpp>
12 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
13 # pragma once
14 #endif
16 // The C++ standard requires that the C float functions are overloarded
17 // for float, double and long double in the std namespace, but some of the older
18 // library implementations don't support this. On some that don't, the C99
19 // float functions (frexpf, frexpl, etc.) are available.
21 // The following tries to automatically detect which are available.
23 namespace boost {
24 namespace hash_detail {
26 // Returned by dummy versions of the float functions.
28 struct not_found {
29 // Implicitly convertible to float and long double in order to avoid
30 // a compile error when the dummy float functions are used.
32 inline operator float() const { return 0; }
33 inline operator long double() const { return 0; }
36 // A type for detecting the return type of functions.
38 template <typename T> struct is;
39 template <> struct is<float> { char x[10]; };
40 template <> struct is<double> { char x[20]; };
41 template <> struct is<long double> { char x[30]; };
42 template <> struct is<boost::hash_detail::not_found> { char x[40]; };
44 // Used to convert the return type of a function to a type for sizeof.
46 template <typename T> is<T> float_type(T);
48 // call_ldexp
50 // This will get specialized for float and long double
52 template <typename Float> struct call_ldexp
54 typedef double float_type;
56 inline double operator()(double a, int b) const
58 using namespace std;
59 return ldexp(a, b);
63 // call_frexp
65 // This will get specialized for float and long double
67 template <typename Float> struct call_frexp
69 typedef double float_type;
71 inline double operator()(double a, int* b) const
73 using namespace std;
74 return frexp(a, b);
80 // A namespace for dummy functions to detect when the actual function we want
81 // isn't available. ldexpl, ldexpf etc. might be added tby the macros below.
83 // AFAICT these have to be outside of the boost namespace, as if they're in
84 // the boost namespace they'll always be preferable to any other function
85 // (since the arguments are built in types, ADL can't be used).
87 namespace boost_hash_detect_float_functions {
88 template <class Float> boost::hash_detail::not_found ldexp(Float, int);
89 template <class Float> boost::hash_detail::not_found frexp(Float, int*);
92 // Macros for generating specializations of call_ldexp and call_frexp.
94 // check_cpp and check_c99 check if the C++ or C99 functions are available.
96 // Then the call_* functions select an appropriate implementation.
98 // I used c99_func in a few places just to get a unique name.
100 // Important: when using 'using namespace' at namespace level, include as
101 // little as possible in that namespace, as Visual C++ has an odd bug which
102 // can cause the namespace to be imported at the global level. This seems to
103 // happen mainly when there's a template in the same namesapce.
105 #define BOOST_HASH_CALL_FLOAT_FUNC(cpp_func, c99_func, type1, type2) \
106 namespace boost_hash_detect_float_functions { \
107 template <class Float> \
108 boost::hash_detail::not_found c99_func(Float, type2); \
111 namespace boost { \
112 namespace hash_detail { \
113 namespace c99_func##_detect { \
114 using namespace std; \
115 using namespace boost_hash_detect_float_functions; \
117 struct check { \
118 static type1 x; \
119 static type2 y; \
120 BOOST_STATIC_CONSTANT(bool, cpp = \
121 sizeof(float_type(cpp_func(x,y))) \
122 == sizeof(is<type1>)); \
123 BOOST_STATIC_CONSTANT(bool, c99 = \
124 sizeof(float_type(c99_func(x,y))) \
125 == sizeof(is<type1>)); \
126 }; \
129 template <bool x> \
130 struct call_c99_##c99_func : \
131 boost::hash_detail::call_##cpp_func<double> {}; \
133 template <> \
134 struct call_c99_##c99_func<true> { \
135 typedef type1 float_type; \
137 template <typename T> \
138 inline type1 operator()(type1 a, T b) const \
140 using namespace std; \
141 return c99_func(a, b); \
143 }; \
145 template <bool x> \
146 struct call_cpp_##c99_func : \
147 call_c99_##c99_func< \
148 ::boost::hash_detail::c99_func##_detect::check::c99 \
149 > {}; \
151 template <> \
152 struct call_cpp_##c99_func<true> { \
153 typedef type1 float_type; \
155 template <typename T> \
156 inline type1 operator()(type1 a, T b) const \
158 using namespace std; \
159 return cpp_func(a, b); \
161 }; \
163 template <> \
164 struct call_##cpp_func<type1> : \
165 call_cpp_##c99_func< \
166 ::boost::hash_detail::c99_func##_detect::check::cpp \
167 > {}; \
171 #define BOOST_HASH_CALL_FLOAT_MACRO(cpp_func, c99_func, type1, type2) \
172 namespace boost { \
173 namespace hash_detail { \
175 template <> \
176 struct call_##cpp_func<type1> { \
177 typedef type1 float_type; \
178 inline type1 operator()(type1 x, type2 y) const { \
179 return c99_func(x, y); \
181 }; \
185 #if defined(ldexpf)
186 BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpf, float, int)
187 #else
188 BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpf, float, int)
189 #endif
191 #if defined(ldexpl)
192 BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpl, long double, int)
193 #else
194 BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpl, long double, int)
195 #endif
197 #if defined(frexpf)
198 BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpf, float, int*)
199 #else
200 BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpf, float, int*)
201 #endif
203 #if defined(frexpl)
204 BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpl, long double, int*)
205 #else
206 BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpl, long double, int*)
207 #endif
209 #undef BOOST_HASH_CALL_FLOAT_MACRO
210 #undef BOOST_HASH_CALL_FLOAT_FUNC
213 namespace boost
215 namespace hash_detail
217 template <typename Float1, typename Float2>
218 struct select_hash_type_impl {
219 typedef double type;
222 template <>
223 struct select_hash_type_impl<float, float> {
224 typedef float type;
227 template <>
228 struct select_hash_type_impl<long double, long double> {
229 typedef long double type;
233 // select_hash_type
235 // If there is support for a particular floating point type, use that
236 // otherwise use double (there's always support for double).
238 template <typename Float>
239 struct select_hash_type : select_hash_type_impl<
240 BOOST_DEDUCED_TYPENAME call_ldexp<Float>::float_type,
241 BOOST_DEDUCED_TYPENAME call_frexp<Float>::float_type
242 > {};
246 #endif