source: vendor/nemo/current/NEMOGCM/EXTERNAL/XIOS/extern/boost/include/boost/functional/hash/detail/float_functions.hpp @ 44

Last change on this file since 44 was 44, checked in by cholod, 12 years ago

Load NEMO_TMP into vendor/nemo/current.

File size: 10.7 KB
Line 
1
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)
5
6#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP)
7#define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP
8
9#include <boost/config.hpp>
10#include <boost/config/no_tr1/cmath.hpp>
11
12#if defined(_MSC_VER) && (_MSC_VER >= 1020)
13# pragma once
14#endif
15
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.
20//
21// The following tries to automatically detect which are available.
22
23namespace boost {
24    namespace hash_detail {
25
26        // Returned by dummy versions of the float functions.
27   
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.
31
32            inline operator float() const { return 0; }
33            inline operator long double() const { return 0; }
34        };
35         
36        // A type for detecting the return type of functions.
37
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]; };
43           
44        // Used to convert the return type of a function to a type for sizeof.
45
46        template <typename T> is<T> float_type(T);
47
48        // call_ldexp
49        //
50        // This will get specialized for float and long double
51       
52        template <typename Float> struct call_ldexp
53        {
54            typedef double float_type;
55           
56            inline double operator()(double a, int b) const
57            {
58                using namespace std;
59                return ldexp(a, b);
60            }
61        };
62
63        // call_frexp
64        //
65        // This will get specialized for float and long double
66
67        template <typename Float> struct call_frexp
68        {
69            typedef double float_type;
70           
71            inline double operator()(double a, int* b) const
72            {
73                using namespace std;
74                return frexp(a, b);
75            }
76        };
77    }
78}
79           
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.
82//
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).
86
87namespace 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*);   
90}
91
92// Macros for generating specializations of call_ldexp and call_frexp.
93//
94// check_cpp and check_c99 check if the C++ or C99 functions are available.
95//
96// Then the call_* functions select an appropriate implementation.
97//
98// I used c99_func in a few places just to get a unique name.
99//
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.
104
105#define BOOST_HASH_CALL_FLOAT_FUNC(cpp_func, c99_func, type1, type2)    \
106namespace boost_hash_detect_float_functions {                           \
107    template <class Float>                                              \
108    boost::hash_detail::not_found c99_func(Float, type2);               \
109}                                                                       \
110                                                                        \
111namespace boost {                                                       \
112    namespace hash_detail {                                             \
113        namespace c99_func##_detect {                                   \
114            using namespace std;                                        \
115            using namespace boost_hash_detect_float_functions;          \
116                                                                        \
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            };                                                          \
127        }                                                               \
128                                                                        \
129        template <bool x>                                               \
130        struct call_c99_##c99_func :                                    \
131            boost::hash_detail::call_##cpp_func<double> {};             \
132                                                                        \
133        template <>                                                     \
134        struct call_c99_##c99_func<true> {                              \
135            typedef type1 float_type;                                   \
136                                                                        \
137            template <typename T>                                       \
138            inline type1 operator()(type1 a, T b)  const                \
139            {                                                           \
140                using namespace std;                                    \
141                return c99_func(a, b);                                  \
142            }                                                           \
143        };                                                              \
144                                                                        \
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            > {};                                                       \
150                                                                        \
151        template <>                                                     \
152        struct call_cpp_##c99_func<true> {                              \
153            typedef type1 float_type;                                   \
154                                                                        \
155            template <typename T>                                       \
156            inline type1 operator()(type1 a, T b)  const                \
157            {                                                           \
158                using namespace std;                                    \
159                return cpp_func(a, b);                                  \
160            }                                                           \
161        };                                                              \
162                                                                        \
163        template <>                                                     \
164        struct call_##cpp_func<type1> :                                 \
165            call_cpp_##c99_func<                                        \
166                ::boost::hash_detail::c99_func##_detect::check::cpp     \
167            > {};                                                       \
168    }                                                                   \
169}
170
171#define BOOST_HASH_CALL_FLOAT_MACRO(cpp_func, c99_func, type1, type2)   \
172namespace boost {                                                       \
173    namespace hash_detail {                                             \
174                                                                        \
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);                                  \
180            }                                                           \
181        };                                                              \
182    }                                                                   \
183}
184
185#if defined(ldexpf)
186BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpf, float, int)
187#else
188BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpf, float, int)
189#endif
190
191#if defined(ldexpl)
192BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpl, long double, int)
193#else
194BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpl, long double, int)
195#endif
196
197#if defined(frexpf)
198BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpf, float, int*)
199#else
200BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpf, float, int*)
201#endif
202
203#if defined(frexpl)
204BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpl, long double, int*)
205#else
206BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpl, long double, int*)
207#endif
208
209#undef BOOST_HASH_CALL_FLOAT_MACRO
210#undef BOOST_HASH_CALL_FLOAT_FUNC
211
212
213namespace boost
214{
215    namespace hash_detail
216    {
217        template <typename Float1, typename Float2>
218        struct select_hash_type_impl {
219            typedef double type;
220        };
221
222        template <>
223        struct select_hash_type_impl<float, float> {
224            typedef float type;
225        };
226
227        template <>
228        struct select_hash_type_impl<long double, long double> {
229            typedef long double type;
230        };
231
232
233        // select_hash_type
234        //
235        // If there is support for a particular floating point type, use that
236        // otherwise use double (there's always support for double).
237             
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            > {};           
243    }
244}
245
246#endif
Note: See TracBrowser for help on using the repository browser.