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