• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "./config.hpp"
7 
8 #ifdef BOOST_HASH_TEST_STD_INCLUDES
9 #  include <functional>
10 #else
11 #  include <boost/container_hash/hash.hpp>
12 #endif
13 
14 #include <boost/core/lightweight_test.hpp>
15 
16 #include <cmath>
17 #include <boost/container_hash/detail/limits.hpp>
18 #include <boost/container_hash/detail/float_functions.hpp>
19 #include <boost/config/workaround.hpp>
20 
21 #include <iostream>
22 
23 #if defined(BOOST_MSVC)
24 #pragma warning(push)
25 #pragma warning(disable:4127)   // conditional expression is constant
26 #pragma warning(disable:4723)   // conditional expression is constant
27 #if BOOST_MSVC < 1400
28 #pragma warning(disable:4267)   // conversion from 'size_t' to 'unsigned int',
29                                 // possible loss of data
30 #endif
31 #endif
32 
33 #if defined(__GNUC__) && !defined(BOOST_INTEL_CXX_VERSION)
34 #pragma GCC diagnostic ignored "-Wfloat-equal"
35 #endif
36 
float_type(float *)37 char const* float_type(float*) { return "float"; }
float_type(double *)38 char const* float_type(double*) { return "double"; }
float_type(long double *)39 char const* float_type(long double*) { return "long double"; }
40 
41 template <class T>
float_tests(char const * name,T * =0)42 void float_tests(char const* name, T* = 0)
43 {
44     std::cerr
45         <<  "\n"
46         <<  "Testing " BOOST_STRINGIZE(BOOST_HASH_TEST_NAMESPACE) "::hash<"
47         <<  name
48         <<  ">\n"
49         <<  "\n"
50         <<  "boost::hash_detail::limits<T>::digits = "
51         <<  boost::hash_detail::limits<T>::digits<< "\n"
52         <<  "boost::hash_detail::limits<int>::digits = "
53         <<  boost::hash_detail::limits<int>::digits<< "\n"
54         <<  "boost::hash_detail::limits<std::size_t>::digits = "
55         <<  boost::hash_detail::limits<std::size_t>::digits
56         <<  "\n"
57         <<  "\n"
58         <<  "boost::hash_detail::call_ldexp<T>::float_type = "
59         <<  float_type(static_cast<BOOST_DEDUCED_TYPENAME
60                 boost::hash_detail::call_ldexp<T>::float_type*>(0))
61         <<  "\n"
62         <<  "boost::hash_detail::call_frexp<T>::float_type = "
63         <<  float_type(static_cast<BOOST_DEDUCED_TYPENAME
64                 boost::hash_detail::call_frexp<T>::float_type*>(0))
65         <<  "\n"
66         <<  "boost::hash_detail::select_hash_type<T>::type = "
67         <<  float_type(static_cast<BOOST_DEDUCED_TYPENAME
68                 boost::hash_detail::select_hash_type<T>::type*>(0))
69         <<  "\n"
70         <<  "\n"
71         ;
72 
73     BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
74 
75     T zero = 0;
76     T minus_zero = (T) -1 * zero;
77 
78     BOOST_TEST(zero == minus_zero);
79     BOOST_TEST(x1(zero) == x1(minus_zero));
80 
81 #if defined(BOOST_HASH_TEST_EXTENSIONS)
82     BOOST_TEST(x1(zero) == BOOST_HASH_TEST_NAMESPACE::hash_value(zero));
83     BOOST_TEST(x1(minus_zero) == BOOST_HASH_TEST_NAMESPACE::hash_value(minus_zero));
84 #endif
85 
86     BOOST_TEST(x1(zero) != x1(0.5));
87     BOOST_TEST(x1(minus_zero) != x1(0.5));
88     BOOST_TEST(x1(0.5) != x1(-0.5));
89     BOOST_TEST(x1(1) != x1(-1));
90 
91     using namespace std;
92 
93 // Doing anything with infinity causes borland to crash.
94 #if defined(__BORLANDC__)
95     std::cerr
96         <<  "Not running infinity checks on Borland, as it causes it to crash."
97             "\n";
98 #else
99     if(boost::hash_detail::limits<T>::has_infinity) {
100         T infinity = -log(zero);
101         T infinity2 = (T) 1. / zero;
102         T infinity3 = (T) -1. / minus_zero;
103         T infinity4 = boost::hash_detail::limits<T>::infinity();
104 
105         T minus_infinity = log(zero);
106         T minus_infinity2 = (T) -1. / zero;
107         T minus_infinity3 = (T) 1. / minus_zero;
108 
109 #if defined(BOOST_HASH_TEST_EXTENSIONS)
110         BOOST_TEST(x1(infinity) == BOOST_HASH_TEST_NAMESPACE::hash_value(infinity));
111         BOOST_TEST(x1(minus_infinity)
112                 == BOOST_HASH_TEST_NAMESPACE::hash_value(minus_infinity));
113 #endif
114 
115         if(infinity == infinity2)
116             BOOST_TEST(x1(infinity) == x1(infinity2));
117         if(infinity == infinity3)
118             BOOST_TEST(x1(infinity) == x1(infinity3));
119         if(infinity == infinity4)
120             BOOST_TEST(x1(infinity) == x1(infinity4));
121 
122         if(minus_infinity == minus_infinity2)
123             BOOST_TEST(x1(minus_infinity) == x1(minus_infinity2));
124         if(minus_infinity == minus_infinity3)
125             BOOST_TEST(x1(minus_infinity) == x1(minus_infinity3));
126 
127         BOOST_TEST(infinity != minus_infinity);
128 
129         if(x1(infinity) == x1(minus_infinity)) {
130             std::cerr<<"x1(infinity) == x1(-infinity) == "<<x1(infinity)<<"\n";
131         }
132 
133         // This should really be 'has_denorm == denorm_present' but some
134         // compilers don't have 'denorm_present'. See also a later use.
135         if(boost::hash_detail::limits<T>::has_denorm) {
136             if(x1(boost::hash_detail::limits<T>::denorm_min()) == x1(infinity))
137             {
138                 std::cerr
139                     <<  "x1(denorm_min) == x1(infinity) == "
140                     <<  x1(infinity)
141                     <<  "\n";
142             }
143 
144             if(x1(boost::hash_detail::limits<T>::denorm_min()) ==
145                 x1(minus_infinity))
146             {
147                 std::cerr
148                     <<  "x1(denorm_min) == x1(-infinity) == "
149                     <<  x1(minus_infinity)
150                     <<  "\n";
151             }
152         }
153 
154         if(boost::hash_detail::limits<T>::has_quiet_NaN) {
155             if(x1(boost::hash_detail::limits<T>::quiet_NaN()) == x1(infinity))
156             {
157                 std::cerr
158                     <<  "x1(quiet_NaN) == x1(infinity) == "
159                     <<  x1(infinity)
160                     <<  "\n";
161             }
162 
163             if(x1(boost::hash_detail::limits<T>::quiet_NaN()) ==
164                 x1(minus_infinity))
165             {
166                 std::cerr
167                     <<  "x1(quiet_NaN) == x1(-infinity) == "
168                     <<  x1(minus_infinity)
169                     <<  "\n";
170             }
171         }
172     }
173 #endif
174 
175     T max = (boost::hash_detail::limits<T>::max)();
176     T half_max = max / 2;
177     T quarter_max = max / 4;
178     T three_quarter_max = max - quarter_max;
179 
180     // Check the limits::max is in range.
181     BOOST_TEST(max != half_max);
182     BOOST_TEST(max != quarter_max);
183     BOOST_TEST(max != three_quarter_max);
184     BOOST_TEST(half_max != quarter_max);
185     BOOST_TEST(half_max != three_quarter_max);
186     BOOST_TEST(quarter_max != three_quarter_max);
187 
188     BOOST_TEST(max != -max);
189     BOOST_TEST(half_max != -half_max);
190     BOOST_TEST(quarter_max != -quarter_max);
191     BOOST_TEST(three_quarter_max != -three_quarter_max);
192 
193 
194 #if defined(BOOST_HASH_TEST_EXTENSIONS)
195     BOOST_TEST(x1(max) == BOOST_HASH_TEST_NAMESPACE::hash_value(max));
196     BOOST_TEST(x1(half_max) == BOOST_HASH_TEST_NAMESPACE::hash_value(half_max));
197     BOOST_TEST(x1(quarter_max) == BOOST_HASH_TEST_NAMESPACE::hash_value(quarter_max));
198     BOOST_TEST(x1(three_quarter_max) ==
199         BOOST_HASH_TEST_NAMESPACE::hash_value(three_quarter_max));
200 #endif
201 
202     // The '!=' tests could legitimately fail, but with my hash it indicates a
203     // bug.
204     BOOST_TEST(x1(max) == x1(max));
205     BOOST_TEST(x1(max) != x1(quarter_max));
206     BOOST_TEST(x1(max) != x1(half_max));
207     BOOST_TEST(x1(max) != x1(three_quarter_max));
208     BOOST_TEST(x1(quarter_max) == x1(quarter_max));
209     BOOST_TEST(x1(quarter_max) != x1(half_max));
210     BOOST_TEST(x1(quarter_max) != x1(three_quarter_max));
211     BOOST_TEST(x1(half_max) == x1(half_max));
212     BOOST_TEST(x1(half_max) != x1(three_quarter_max));
213     BOOST_TEST(x1(three_quarter_max) == x1(three_quarter_max));
214 
215     BOOST_TEST(x1(max) != x1(-max));
216     BOOST_TEST(x1(half_max) != x1(-half_max));
217     BOOST_TEST(x1(quarter_max) != x1(-quarter_max));
218     BOOST_TEST(x1(three_quarter_max) != x1(-three_quarter_max));
219 
220 
221 // Intel with gcc stdlib sometimes segfaults on calls to asin and acos.
222 #if !((defined(__INTEL_COMPILER) || defined(__ICL) || \
223         defined(__ICC) || defined(__ECC)) && \
224     (defined(__GLIBCPP__) || defined(__GLIBCXX__)))
225     T v1 = asin((T) 1);
226     T v2 = acos((T) 0);
227     if(v1 == v2)
228         BOOST_TEST(x1(v1) == x1(v2));
229 
230 #if defined(BOOST_HASH_TEST_EXTENSIONS)
231     BOOST_TEST(x1(v1) == BOOST_HASH_TEST_NAMESPACE::hash_value(v1));
232     BOOST_TEST(x1(v2) == BOOST_HASH_TEST_NAMESPACE::hash_value(v2));
233 #endif
234 
235 #endif
236 
237 #if defined(BOOST_HASH_TEST_EXTENSIONS)
238     BOOST_TEST(x1(boost::hash_detail::limits<T>::epsilon()) ==
239             BOOST_HASH_TEST_NAMESPACE::hash_value(
240                 boost::hash_detail::limits<T>::epsilon()));
241 #endif
242 
243     BOOST_TEST(boost::hash_detail::limits<T>::epsilon() != (T) 0);
244     if(x1(boost::hash_detail::limits<T>::epsilon()) == x1((T) 0))
245         std::cerr<<"x1(epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
246 
247     BOOST_TEST(-boost::hash_detail::limits<T>::epsilon() != (T) 0);
248     if(x1(-boost::hash_detail::limits<T>::epsilon()) == x1((T) 0))
249         std::cerr<<"x1(-epsilon) == x1(0) == "<<x1((T) 0)<<"\n";
250 
251     BOOST_TEST((T) 1 + boost::hash_detail::limits<T>::epsilon() != (T) 1);
252     if(x1((T) 1 + boost::hash_detail::limits<T>::epsilon()) == x1((T) 1))
253         std::cerr<<"x1(1 + epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
254 
255     BOOST_TEST((T) 1 - boost::hash_detail::limits<T>::epsilon() != (T) 1);
256     if(x1((T) 1 - boost::hash_detail::limits<T>::epsilon()) == x1((T) 1))
257         std::cerr<<"x1(1 - epsilon) == x1(1) == "<<x1((T) 1)<<"\n";
258 
259     BOOST_TEST((T) -1 + boost::hash_detail::limits<T>::epsilon() != (T) -1);
260     if(x1((T) -1 + boost::hash_detail::limits<T>::epsilon()) == x1((T) -1))
261         std::cerr<<"x1(-1 + epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
262 
263     BOOST_TEST((T) -1 - boost::hash_detail::limits<T>::epsilon() != (T) -1);
264     if(x1((T) -1 - boost::hash_detail::limits<T>::epsilon()) == x1((T) -1))
265         std::cerr<<"x1(-1 - epsilon) == x1(-1) == "<<x1((T) -1)<<"\n";
266 
267     // As before.
268     if(boost::hash_detail::limits<T>::has_denorm) {
269         if(x1(boost::hash_detail::limits<T>::denorm_min()) == x1(zero)) {
270             std::cerr<<"x1(denorm_min) == x1(zero) == "<<x1(zero)<<"\n";
271         }
272 #if !BOOST_WORKAROUND(__DECCXX_VER,<70190006) && defined(BOOST_HASH_TEST_EXTENSIONS)
273         // The Tru64/CXX standard library prior to 7.1 contains a bug in the
274         // specialization of boost::hash_detail::limits::denorm_min() for long
275         // doubles which causes this test to fail.
276         if(x1(boost::hash_detail::limits<T>::denorm_min()) !=
277             BOOST_HASH_TEST_NAMESPACE::hash_value(
278                 boost::hash_detail::limits<T>::denorm_min()))
279         {
280             std::cerr
281                 <<  "x1(boost::hash_detail::limits<T>::denorm_min()) = "
282                 <<  x1(boost::hash_detail::limits<T>::denorm_min())
283                 <<  "\nhash_value(boost::hash_detail::limits<T>::denorm_min())"
284                     " = "
285                 <<  BOOST_HASH_TEST_NAMESPACE::hash_value(
286                         boost::hash_detail::limits<T>::denorm_min())
287                 <<  "\nx1(0) = "
288                 <<  x1(0)
289                 <<  "\n";
290         }
291 #endif
292     }
293 
294 // NaN also causes borland to crash.
295 #if !defined(__BORLANDC__) && defined(BOOST_HASH_TEST_EXTENSIONS)
296     if(boost::hash_detail::limits<T>::has_quiet_NaN) {
297         if(x1(boost::hash_detail::limits<T>::quiet_NaN()) == x1(1.0)) {
298             std::cerr<<"x1(quiet_NaN) == x1(1.0) == "<<x1(1.0)<<"\n";
299         }
300         BOOST_TEST(x1(boost::hash_detail::limits<T>::quiet_NaN()) ==
301             BOOST_HASH_TEST_NAMESPACE::hash_value(
302                 boost::hash_detail::limits<T>::quiet_NaN()));
303     }
304 #endif
305 }
306 
307 #if defined(BOOST_MSVC)
308 #pragma warning(pop)
309 #endif
310