Hello Daniel, I have succefully performed the two unit test. Below you can find the output. I have performed the test for my compiler in 32 and 64 bit with and without exception mask. The test are in accordance with my application. Best Johannes ================================================================================ 1. hash_float_test on msvc 2008 9.0.30729.1SP, 32Bit, no SSE2, no exception mask Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<float> boost::hash_detail::limits<T>::digits = 24 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = float boost::hash_detail::call_frexp<T>::float_type = float boost::hash_detail::select_hash_type<T>::type = float x1(infinity) == x1(-infinity) == 4294967295 x1(quiet_NaN) == x1(infinity) == 4294967295 x1(quiet_NaN) == x1(-infinity) == 4294967295 Testing boost::hash<double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = double boost::hash_detail::call_frexp<T>::float_type = double boost::hash_detail::select_hash_type<T>::type = double x1(infinity) == x1(-infinity) == 4294967295 x1(quiet_NaN) == x1(infinity) == 4294967295 x1(quiet_NaN) == x1(-infinity) == 4294967295 Drücken Sie eine beliebige Taste . . . ================================================================================ 2. hash_float_test on msvc 2008 9.0.30729.1SP, 64Bit, SSE2, no exception mask Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<float> boost::hash_detail::limits<T>::digits = 24 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 64 boost::hash_detail::call_ldexp<T>::float_type = float boost::hash_detail::call_frexp<T>::float_type = float boost::hash_detail::select_hash_type<T>::type = float x1(infinity) == x1(-infinity) == 2882303761517117439 x1(quiet_NaN) == x1(infinity) == 2882303761517117439 x1(quiet_NaN) == x1(-infinity) == 2882303761517117439 Testing boost::hash<double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 64 boost::hash_detail::call_ldexp<T>::float_type = double boost::hash_detail::call_frexp<T>::float_type = double boost::hash_detail::select_hash_type<T>::type = double x1(infinity) == x1(-infinity) == 2882303761517117439 x1(quiet_NaN) == x1(infinity) == 2882303761517117439 x1(quiet_NaN) == x1(-infinity) == 2882303761517117439 Drücken Sie eine beliebige Taste . . . ================================================================================ 3. hash_float_test on msvc 2008 9.0.30729.1SP, 32Bit, no SSE2, with exception mask unsigned int flag = _control87(0,0); _control87(0x0,_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW); Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<float> boost::hash_detail::limits<T>::digits = 24 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = float boost::hash_detail::call_frexp<T>::float_type = float boost::hash_detail::select_hash_type<T>::type = float raise exception: T infinity = -log(zero); ================================================================================ 4. hash_float_test on msvc 2008 9.0.30729.1SP, 64Bit, SSE2, with exception mask unsigned int flag = _control87(0,0); _control87(0x0,_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW); Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<float> boost::hash_detail::limits<T>::digits = 24 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 64 boost::hash_detail::call_ldexp<T>::float_type = float boost::hash_detail::call_frexp<T>::float_type = float boost::hash_detail::select_hash_type<T>::type = float raise exception: template <class T> inline std::size_t float_hash_impl2(T v) { boost::hash_detail::call_frexp<T> frexp; boost::hash_detail::call_ldexp<T> ldexp; int exp = 0; v = frexp(v, &exp); // A postive value is easier to hash, so combine the // sign with the exponent and use the absolute value. if(v < 0) { v = -v; exp += limits<T>::max_exponent - limits<T>::min_exponent; } v = ldexp(v, limits<std::size_t>::digits); -----> std::size_t seed = static_cast<std::size_t>(v); v -= static_cast<T>(seed); // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; std::size_t const length = (limits<T>::digits * boost::static_log2<limits<T>::radix>::value + limits<std::size_t>::digits - 1) / limits<std::size_t>::digits; for(std::size_t i = 0; i != length; ++i) { v = ldexp(v, limits<std::size_t>::digits); std::size_t part = static_cast<std::size_t>(v); v -= static_cast<T>(part); hash_float_combine(seed, part); } hash_float_combine(seed, exp); return seed; } ================================================================================ 5. hash_long_double_test on msvc 2008 9.0.30729.1SP, 32Bit, SSE2, no exception mask Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<long double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = long double boost::hash_detail::call_frexp<T>::float_type = long double boost::hash_detail::select_hash_type<T>::type = long double x1(infinity) == x1(-infinity) == 4294967295 x1(quiet_NaN) == x1(infinity) == 4294967295 x1(quiet_NaN) == x1(-infinity) == 4294967295 Drücken Sie eine beliebige Taste . . . ================================================================================ 6. hash_long_double_test on msvc 2008 9.0.30729.1SP, 64Bit, SSE2, no exception mask Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<long double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = long double boost::hash_detail::call_frexp<T>::float_type = long double boost::hash_detail::select_hash_type<T>::type = long double x1(infinity) == x1(-infinity) == 4294967295 x1(quiet_NaN) == x1(infinity) == 4294967295 x1(quiet_NaN) == x1(-infinity) == 4294967295 Drücken Sie eine beliebige Taste . . . ================================================================================ 7. hash_long_double_test on msvc 2008 9.0.30729.1SP, 32Bit, SSE2, with exception mask unsigned int flag = _control87(0,0); _control87(0x0,_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW); Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<long double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 32 boost::hash_detail::call_ldexp<T>::float_type = long double boost::hash_detail::call_frexp<T>::float_type = long double boost::hash_detail::select_hash_type<T>::type = long double raise exception: T infinity = -log(zero); ================================================================================ 8. hash_long_double_test on msvc 2008 9.0.30729.1SP, 64Bit, SSE2, with exception mask unsigned int flag = _control87(0,0); _control87(0x0,_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW); Compiler: Microsoft Visual C++ version 9.0 Platform: Win32 Library: Dinkumware standard library version 505 Testing boost::hash<long double> boost::hash_detail::limits<T>::digits = 53 boost::hash_detail::limits<int>::digits = 31 boost::hash_detail::limits<std::size_t>::digits = 64 boost::hash_detail::call_ldexp<T>::float_type = long double boost::hash_detail::call_frexp<T>::float_type = long double boost::hash_detail::select_hash_type<T>::type = long double raise exception: template <class T> inline std::size_t float_hash_impl2(T v) { boost::hash_detail::call_frexp<T> frexp; boost::hash_detail::call_ldexp<T> ldexp; int exp = 0; v = frexp(v, &exp); // A postive value is easier to hash, so combine the // sign with the exponent and use the absolute value. if(v < 0) { v = -v; exp += limits<T>::max_exponent - limits<T>::min_exponent; } v = ldexp(v, limits<std::size_t>::digits); -----> std::size_t seed = static_cast<std::size_t>(v); v -= static_cast<T>(seed); // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; std::size_t const length = (limits<T>::digits * boost::static_log2<limits<T>::radix>::value + limits<std::size_t>::digits - 1) / limits<std::size_t>::digits; for(std::size_t i = 0; i != length; ++i) { v = ldexp(v, limits<std::size_t>::digits); std::size_t part = static_cast<std::size_t>(v); v -= static_cast<T>(part); hash_float_combine(seed, part); } hash_float_combine(seed, exp); return seed; } v = ldexp(v, limits<std::size_t>::digits); 000000013F4240F1 mov r8d,40h 000000013F4240F7 movsd xmm1,mmword ptr [v] 000000013F424100 lea rcx,[ldexp] 000000013F424105 call boost::hash_detail::call_cpp_ldexpl<1>::operator()<int> (13F42107Dh) 000000013F42410A movsd mmword ptr [v],xmm0 std::size_t seed = static_cast<std::size_t>(v); 000000013F424113 xor ecx,ecx 000000013F424115 movsd xmm0,mmword ptr [v] 000000013F42411E comisd xmm0,mmword ptr [__real@43e0000000000000 (13F42E568h)] 000000013F424126 jbe boost::hash_detail::float_hash_impl2<long double>+0D7h (13F424147h) 000000013F424128 subsd xmm0,mmword ptr [__real@43e0000000000000 (13F42E568h)] 000000013F424130 comisd xmm0,mmword ptr [__real@43e0000000000000 (13F42E568h)] 000000013F424138 jae boost::hash_detail::float_hash_impl2<long double>+0D7h (13F424147h) 000000013F42413A mov rax,8000000000000000h 000000013F424144 add rcx,rax ---->000000013F424147 cvttsd2si rax,xmm0 000000013F42414C add rax,rcx 000000013F42414F mov qword ptr [seed],rax v -= static_cast<T>(seed); "Daniel James" <dnljms@gmail.com> schrieb im Newsbeitrag news:CAHOE3ycbT6fjMOcDvKcrk95UV4uwOgdkdjXLTN_D5a-OACU7BQ@mail.gmail.com...
On 21 August 2012 13:21, Johannes Brunen <JBrunen@datasolid.de> wrote:
I see two problems running the unit test: 1. I would have to setup the runtime for 64 bit including the mentioned exception mask. 2. I'm not proficient in the usage of the unit test framework.
You just need to build the .cpp file and run it. Each one is a self-contained program - no linking is required, just remember to add boost's root to the include path. So you can use whatever build setup you normally use.
How can I change the hash function used for floats and doubles, respectively? Do you have an example for hashing the binary representation?
I have to write it first. It's a change to the implementation.
I also use the multi_index container with a hashed_index on floats. I see the very same problems lurking on this side. If this is a real problem it might be worth to change the implementation of the hash function in general?
Yes, it's an issue in the hash function not the container.