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