Use boosts std::hash<...> functionality for hash functions
[dyninst.git] / external / boost / functional / detail / hash_float.hpp
1
2 //  Copyright Daniel James 2005-2006. Use, modification, and distribution are
3 //  subject to 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 //  Based on Peter Dimov's proposal
7 //  http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
8 //  issue 6.18. 
9
10 #if !defined(BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER)
11 #define BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER
12
13 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
14 # pragma once
15 #endif
16 #if defined(__GNUC__)
17 #pragma GCC system_header
18 #endif
19
20 #include <boost/functional/detail/float_functions.hpp>
21 #include <boost/limits.hpp>
22 #include <boost/assert.hpp>
23 #include <errno.h>
24
25 // Don't use fpclassify or _fpclass for stlport.
26 #if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
27 #  if defined(__GLIBCPP__) || defined(__GLIBCXX__)
28 // GNU libstdc++ 3
29 #    if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \
30         !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
31 #      define BOOST_HASH_USE_FPCLASSIFY
32 #    endif
33 #  elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
34 // Dinkumware Library, on Visual C++ 
35 #    if defined(BOOST_MSVC)
36 #      define BOOST_HASH_USE_FPCLASS
37 #    endif
38 #  endif
39 #endif
40
41 namespace boost
42 {
43     namespace hash_detail
44     {
45         inline void hash_float_combine(std::size_t& seed, std::size_t value)
46         {
47             seed ^= value + (seed<<6) + (seed>>2);
48         }
49
50         template <class T>
51         inline std::size_t float_hash_impl(T v)
52         {
53             int exp = 0;
54             errno = 0;
55             v = boost::hash_detail::call_frexp(v, &exp);
56             if(errno) return 0;
57
58             std::size_t seed = 0;
59
60             std::size_t const length
61                 = (std::numeric_limits<T>::digits +
62                         std::numeric_limits<int>::digits - 1)
63                 / std::numeric_limits<int>::digits;
64
65             for(std::size_t i = 0; i < length; ++i)
66             {
67                 v = boost::hash_detail::call_ldexp(v, std::numeric_limits<int>::digits);
68                 int const part = static_cast<int>(v);
69                 v -= part;
70                 hash_float_combine(seed, part);
71             }
72
73             hash_float_combine(seed, exp);
74
75             return seed;
76         }
77
78         template <class T>
79         inline std::size_t float_hash_value(T v)
80         {
81 #if defined(BOOST_HASH_USE_FPCLASSIFY)
82             using namespace std;
83             switch (fpclassify(v)) {
84             case FP_ZERO:
85                 return 0;
86             case FP_INFINITE:
87                 return (std::size_t)(v > 0 ? -1 : -2);
88             case FP_NAN:
89                 return (std::size_t)(-3);
90             case FP_NORMAL:
91             case FP_SUBNORMAL:
92                 return float_hash_impl(v);
93             default:
94                 BOOST_ASSERT(0);
95                 return 0;
96             }
97 #elif defined(BOOST_HASH_USE_FPCLASS)
98             switch(_fpclass(v)) {
99             case _FPCLASS_NZ:
100             case _FPCLASS_PZ:
101                 return 0;
102             case _FPCLASS_PINF:
103                 return (std::size_t)(-1);
104             case _FPCLASS_NINF:
105                 return (std::size_t)(-2);
106             case _FPCLASS_SNAN:
107             case _FPCLASS_QNAN:
108                 return (std::size_t)(-3);
109             case _FPCLASS_NN:
110             case _FPCLASS_ND:
111                 return float_hash_impl(v);
112             case _FPCLASS_PD:
113             case _FPCLASS_PN:
114                 return float_hash_impl(v);
115             default:
116                 BOOST_ASSERT(0);
117                 return 0;
118             }
119 #else
120             return float_hash_impl(v);
121 #endif
122         }
123     }
124 }
125
126 #endif