Boost logo

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