// Copyright 2005-2009 Daniel James. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP) #define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP #include #include #include #include //#include #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif // The C++ standard requires that the C float functions are overloarded // for float, double and long double in the std namespace, but some of the older // library implementations don't support this. On some that don't, the C99 // float functions (frexpf, frexpl, etc.) are available. // // The following tries to automatically detect which are available. namespace BOOST_HASH_DETECT_FLOAT_FUNCTIONS { // Dummy functions to detect when the actual function we want isn't // available. // // AFAICT these have to be outside of the boost namespace, as if they're in // the boost namespace they'll always be preferable to any other function // (since the arguments are built in types, ADL can't be used). struct none {}; none ldexpf(int, int); none ldexpl(int, int); none frexpf(int, int*); none frexpl(int, int*); template none ldexp(Float, int); template none frexp(Float, int*); } namespace boost { namespace hash_detail { namespace detect { using namespace std; using namespace BOOST_HASH_DETECT_FLOAT_FUNCTIONS; // A type for detecting return type of functions. template struct is; template <> struct is { char x[10]; }; template <> struct is { char x[20]; }; template <> struct is { char x[30]; }; template <> struct is { char x[40]; }; // Convert the return type of a function to a type we can use. template is float_type(T); #define BOOST_HASH_CALL_FLOAT_FUNC(func, type2) \ struct func##_access { \ template \ struct check \ { \ static Float x; \ static type2 y; \ BOOST_STATIC_CONSTANT(bool, value = \ sizeof(float_type(func(x,y))) \ == sizeof(is)); \ }; \ \ template \ struct call \ { \ Float operator()(Float a, type2 b) const \ { \ return func(a, b); \ } \ }; \ } BOOST_HASH_CALL_FLOAT_FUNC(ldexpf, int); BOOST_HASH_CALL_FLOAT_FUNC(ldexpl, int); BOOST_HASH_CALL_FLOAT_FUNC(ldexp, int); BOOST_HASH_CALL_FLOAT_FUNC(frexpf, int*); BOOST_HASH_CALL_FLOAT_FUNC(frexpl, int*); BOOST_HASH_CALL_FLOAT_FUNC(frexp, int*); #undef BOOST_CALL_HAS_FLOAT_FUNC } // check // // Use in select_impl to help old compilers with a value template. template struct check : Access::BOOST_NESTED_TEMPLATE check {}; // found_impl // // Used in select_impl when an appropriate function has // been found. template struct found_impl { // Ignore further types template struct x { typedef found_impl type; }; // Use Access for result struct type : Access::BOOST_NESTED_TEMPLATE call { BOOST_STATIC_CONSTANT(bool, value = true); }; }; // select_impl // // Used to choose which floating point function to use for a particular // floating point type. struct select_impl { // Check if Access is appropriate for Float template struct x : boost::detail::if_true < ::boost::hash_detail::check::value > ::BOOST_NESTED_TEMPLATE then< found_impl, select_impl > {}; // Result for nothing found. struct type { BOOST_STATIC_CONSTANT(bool, value = false); }; }; // call_ldexp // // call_ldexp::value = Is there an appropriate version of call_ldexp // for this type? // Is there is, this is a function object that will call that overload template struct call_ldexp; template <> struct call_ldexp : select_impl :: x::type :: x::type :: type {}; template <> struct call_ldexp : select_impl :: x::type :: type {}; template <> struct call_ldexp : select_impl :: x::type :: x::type :: type {}; // call_frexp // // call_frexp::value = Is there an appropriate version of call_frexp // for this type? // Is there is, this is a function object that will call that overload template struct call_frexp; template <> struct call_frexp : select_impl :: x::type :: x::type :: type {}; template <> struct call_frexp : select_impl :: x::type :: type {}; template <> struct call_frexp : select_impl :: x::type :: x::type :: type {}; // has_float_functions // // Is there an overload of frexp and ldexp for the given float type. template struct has_float_functions { BOOST_STATIC_CONSTANT(bool, value = ( ::boost::type_traits::ice_and< ::boost::hash_detail::call_ldexp::value, ::boost::hash_detail::call_frexp::value >::value )); }; // select_hash_type // // If there is support for a particular floating point type, use that // otherwise use double (there's always support for double). template struct select_hash_type : boost::detail::if_true < ::boost::hash_detail::has_float_functions::value > ::BOOST_NESTED_TEMPLATE then < Float, double > {}; } } #endif