|
Boost Users : |
Subject: Re: [Boost-users] [unordered_map]: Unexpected exception onvalueinsertion
From: Johannes Brunen (JBrunen_at_[hidden])
Date: 2012-08-21 10:59:30
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_at_43e0000000000000
(13F42E568h)]
000000013F424126 jbe boost::hash_detail::float_hash_impl2<long
double>+0D7h (13F424147h)
000000013F424128 subsd xmm0,mmword ptr [__real_at_43e0000000000000
(13F42E568h)]
000000013F424130 comisd xmm0,mmword ptr [__real_at_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_at_[hidden]> schrieb im Newsbeitrag
news:CAHOE3ycbT6fjMOcDvKcrk95UV4uwOgdkdjXLTN_D5a-OACU7BQ_at_mail.gmail.com...
> On 21 August 2012 13:21, Johannes Brunen <JBrunen_at_[hidden]> 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.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net