diff options
Diffstat (limited to 'boost/spirit/home/support/detail/math/detail/fp_traits.hpp')
-rw-r--r-- | boost/spirit/home/support/detail/math/detail/fp_traits.hpp | 583 |
1 files changed, 0 insertions, 583 deletions
diff --git a/boost/spirit/home/support/detail/math/detail/fp_traits.hpp b/boost/spirit/home/support/detail/math/detail/fp_traits.hpp deleted file mode 100644 index 199712a3b9..0000000000 --- a/boost/spirit/home/support/detail/math/detail/fp_traits.hpp +++ /dev/null @@ -1,583 +0,0 @@ -// fp_traits.hpp - -#ifndef BOOST_SPIRIT_MATH_FP_TRAITS_HPP -#define BOOST_SPIRIT_MATH_FP_TRAITS_HPP - -// Copyright (c) 2006 Johan Rade - -// 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(__vms) && defined(__DECCXX) && !__IEEE_FLOAT -# error The VAX floating point mode on VMS is not supported. -#endif - -#if defined(_MSC_VER) -#pragma once -#endif - -#include <cstring> - -#include <boost/assert.hpp> -#include <boost/cstdint.hpp> -#include <boost/detail/endian.hpp> -#include <boost/static_assert.hpp> -#include <boost/type_traits/is_floating_point.hpp> - -//------------------------------------------------------------------------------ - -namespace boost { -namespace spirit { -namespace math { -namespace detail { - -//------------------------------------------------------------------------------ - -/* -Most processors support three different floating point precisions: -single precision (32 bits), double precision (64 bits) -and extended double precision (>64 bits) - -Note that the C++ type long double can be implemented -both as double precision and extended double precision. -*/ - -struct single_precision_tag {}; -struct double_precision_tag {}; -struct extended_double_precision_tag {}; - -//------------------------------------------------------------------------------ - -/* -template<class T, class U> struct fp_traits_impl; - - This is traits class that describes the binary structure of floating - point numbers of C++ type T and precision U - -Requirements: - - T = float, double or long double - U = single_precision_tag, double_precision_tag - or extended_double_precision_tag - -Typedef members: - - bits -- the target type when copying the leading bytes of a floating - point number. It is a typedef for uint32_t or uint64_t. - - coverage -- tells us whether all bytes are copied or not. - It is a typedef for all_bits or not_all_bits. - -Static data members: - - sign, exponent, flag, mantissa -- bit masks that give the meaning of the bits - in the leading bytes. - -Static function members: - - init() -- initializes the static data members, if needed. - (Is a no-op in the specialized versions of the template.) - - get_bits(), set_bits() -- provide access to the leading bytes. -*/ - -struct all_bits {}; -struct not_all_bits {}; - -// Generic version ------------------------------------------------------------- - -// The generic version uses run time initialization to determine the floating -// point format. It is capable of handling most formats, -// but not the Motorola 68K extended double precision format. - -// Currently the generic version is used only for extended double precision -// on Itanium. In all other cases there are specializations of the template -// that use compile time initialization. - -template<class T> struct uint32_t_coverage -{ - typedef not_all_bits type; -}; - -template<> struct uint32_t_coverage<single_precision_tag> -{ - typedef all_bits type; -}; - -template<class T, class U> struct fp_traits_impl -{ - typedef uint32_t bits; - typedef BOOST_DEDUCED_TYPENAME uint32_t_coverage<U>::type coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - static uint32_t exponent; - static uint32_t flag; - static uint32_t mantissa; - - static void init() - { - if(is_init_) return; - do_init_(); - is_init_ = true; - } - - static void get_bits(T x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); - } - - static void set_bits(T& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); - } - -private: - static size_t offset_; - static bool is_init_; - static void do_init_(); -}; - -//.............................................................................. - -template<class T, class U> uint32_t fp_traits_impl<T,U>::exponent; -template<class T, class U> uint32_t fp_traits_impl<T,U>::flag; -template<class T, class U> uint32_t fp_traits_impl<T,U>::mantissa; -template<class T, class U> size_t fp_traits_impl<T,U>::offset_; -template<class T, class U> bool fp_traits_impl<T,U>::is_init_; - -// In a single-threaded program, do_init will be called exactly once. -// In a multi-threaded program, do_init may be called simultaneously -// by more then one thread. That should not be a problem. - -//.............................................................................. - -template<class T, class U> void fp_traits_impl<T,U>::do_init_() -{ - T x = static_cast<T>(3) / static_cast<T>(4); - // sign bit = 0 - // exponent: first and last bit = 0, all other bits = 1 - // flag bit (if present) = 1 - // mantissa: first bit = 1, all other bits = 0 - - uint32_t a; - - for(size_t k = 0; k <= sizeof(T) - 4; ++k) { - - memcpy(&a, reinterpret_cast<unsigned char*>(&x) + k, 4); - - switch(a) { - - case 0x3f400000: // IEEE single precision format - - offset_ = k; - exponent = 0x7f800000; - flag = 0x00000000; - mantissa = 0x007fffff; - return; - - case 0x3fe80000: // IEEE double precision format - // and PowerPC extended double precision format - offset_ = k; - exponent = 0x7ff00000; - flag = 0x00000000; - mantissa = 0x000fffff; - return; - - case 0x3ffe0000: // Motorola extended double precision format - - // Must not get here. Must be handled by specialization. - // To get accurate cutoff between normals and subnormals - // we must use the flag bit that is in the 5th byte. - // Otherwise this cutoff will be off by a factor 2. - // If we do get here, then we have failed to detect the Motorola - // processor at compile time. - - BOOST_ASSERT(false && - "Failed to detect the Motorola processor at compile time"); - return; - - case 0x3ffe8000: // IEEE extended double precision format - // with 15 exponent bits - offset_ = k; - exponent = 0x7fff0000; - flag = 0x00000000; - mantissa = 0x0000ffff; - return; - - case 0x3ffec000: // Intel extended double precision format - - offset_ = k; - exponent = 0x7fff0000; - flag = 0x00008000; - mantissa = 0x00007fff; - return; - - default: - continue; - } - } - - BOOST_ASSERT(false); - - // Unknown format. -} - - -// float (32 bits) ------------------------------------------------------------- - -template<> struct fp_traits_impl<float, single_precision_tag> -{ - typedef uint32_t bits; - typedef all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7f800000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x007fffff); - - static void init() {} - static void get_bits(float x, uint32_t& a) { memcpy(&a, &x, 4); } - static void set_bits(float& x, uint32_t a) { memcpy(&x, &a, 4); } -}; - - -// double (64 bits) ------------------------------------------------------------ - -#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) - -template<> struct fp_traits_impl<double, double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff); - - static void init() {} - - static void get_bits(double x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); - } - - static void set_bits(double& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); - } - -private: - -#if defined(BOOST_BIG_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 0); -#elif defined(BOOST_LITTLE_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 4); -#else - BOOST_STATIC_ASSERT(false); -#endif -}; - -//.............................................................................. - -#else - -template<> struct fp_traits_impl<double, double_precision_tag> -{ - typedef uint64_t bits; - typedef all_bits coverage; - - static const uint64_t sign = (uint64_t)0x80000000 << 32; - static const uint64_t exponent = (uint64_t)0x7ff00000 << 32; - static const uint64_t flag = 0; - static const uint64_t mantissa - = ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff; - - static void init() {} - static void get_bits(double x, uint64_t& a) { memcpy(&a, &x, 8); } - static void set_bits(double& x, uint64_t a) { memcpy(&x, &a, 8); } -}; - -#endif - - -// long double (64 bits) ------------------------------------------------------- - -#if defined(BOOST_NO_INT64_T) || defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) - -template<> struct fp_traits_impl<long double, double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff); - - static void init() {} - - static void get_bits(long double x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); - } - - static void set_bits(long double& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); - } - -private: - -#if defined(BOOST_BIG_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 0); -#elif defined(BOOST_LITTLE_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 4); -#else - BOOST_STATIC_ASSERT(false); -#endif -}; - -//.............................................................................. - -#else - -template<> struct fp_traits_impl<long double, double_precision_tag> -{ - typedef uint64_t bits; - typedef all_bits coverage; - - static const uint64_t sign = (uint64_t)0x80000000 << 32; - static const uint64_t exponent = (uint64_t)0x7ff00000 << 32; - static const uint64_t flag = 0; - static const uint64_t mantissa - = ((uint64_t)0x000fffff << 32) + (uint64_t)0xffffffff; - - static void init() {} - static void get_bits(long double x, uint64_t& a) { memcpy(&a, &x, 8); } - static void set_bits(long double& x, uint64_t a) { memcpy(&x, &a, 8); } -}; - -#endif - - -// long double (>64 bits), x86 and x64 ----------------------------------------- - -#if defined(__i386) || defined(__i386__) || defined(_M_IX86) \ - || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) \ - || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) - -// Intel extended double precision format (80 bits) - -template<> struct fp_traits_impl<long double, extended_double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff); - - static void init() {} - - static void get_bits(long double x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + 6, 4); - } - - static void set_bits(long double& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + 6, &a, 4); - } -}; - - -// long double (>64 bits), Itanium --------------------------------------------- - -#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) - -// The floating point format is unknown at compile time -// No template specialization is provided. -// The generic definition is used. - -// The Itanium supports both -// the Intel extended double precision format (80 bits) and -// the IEEE extended double precision format with 15 exponent bits (128 bits). - - -// long double (>64 bits), PowerPC --------------------------------------------- - -#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) \ - || defined(__ppc) || defined(__ppc__) || defined(__PPC__) - -// PowerPC extended double precision format (128 bits) - -template<> struct fp_traits_impl<long double, extended_double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7ff00000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x000fffff); - - static void init() {} - - static void get_bits(long double x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); - } - - static void set_bits(long double& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); - } - -private: - -#if defined(BOOST_BIG_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 0); -#elif defined(BOOST_LITTLE_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 12); -#else - BOOST_STATIC_ASSERT(false); -#endif -}; - - -// long double (>64 bits), Motorola 68K ---------------------------------------- - -#elif defined(__m68k) || defined(__m68k__) \ - || defined(__mc68000) || defined(__mc68000__) \ - -// Motorola extended double precision format (96 bits) - -// It is the same format as the Intel extended double precision format, -// except that 1) it is big-endian, 2) the 3rd and 4th byte are padding, and -// 3) the flag bit is not set for infinity - -template<> struct fp_traits_impl<long double, extended_double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00008000); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x00007fff); - - static void init() {} - - // copy 1st, 2nd, 5th and 6th byte. 3rd and 4th byte are padding. - - static void get_bits(long double x, uint32_t& a) - { - memcpy(&a, &x, 2); - memcpy(reinterpret_cast<unsigned char*>(&a) + 2, - reinterpret_cast<const unsigned char*>(&x) + 4, 2); - } - - static void set_bits(long double& x, uint32_t a) - { - memcpy(&x, &a, 2); - memcpy(reinterpret_cast<unsigned char*>(&x) + 4, - reinterpret_cast<const unsigned char*>(&a) + 2, 2); - } -}; - - -// long double (>64 bits), All other processors -------------------------------- - -#else - -// IEEE extended double precision format with 15 exponent bits (128 bits) - -template<> struct fp_traits_impl<long double, extended_double_precision_tag> -{ - typedef uint32_t bits; - typedef not_all_bits coverage; - - BOOST_STATIC_CONSTANT(uint32_t, sign = 0x80000000); - BOOST_STATIC_CONSTANT(uint32_t, exponent = 0x7fff0000); - BOOST_STATIC_CONSTANT(uint32_t, flag = 0x00000000); - BOOST_STATIC_CONSTANT(uint32_t, mantissa = 0x0000ffff); - - static void init() {} - - static void get_bits(long double x, uint32_t& a) - { - memcpy(&a, reinterpret_cast<const unsigned char*>(&x) + offset_, 4); - } - - static void set_bits(long double& x, uint32_t a) - { - memcpy(reinterpret_cast<unsigned char*>(&x) + offset_, &a, 4); - } - -private: - -#if defined(BOOST_BIG_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 0); -#elif defined(BOOST_LITTLE_ENDIAN) - BOOST_STATIC_CONSTANT(int, offset_ = 12); -#else - BOOST_STATIC_ASSERT(false); -#endif -}; - -#endif - - -//------------------------------------------------------------------------------ - -// size_to_precision is a type switch for converting a C++ floating point type -// to the corresponding precision type. - -template<int n> struct size_to_precision; - -template<> struct size_to_precision<4> -{ - typedef single_precision_tag type; -}; - -template<> struct size_to_precision<8> -{ - typedef double_precision_tag type; -}; - -template<> struct size_to_precision<10> -{ - typedef extended_double_precision_tag type; -}; - -template<> struct size_to_precision<12> -{ - typedef extended_double_precision_tag type; -}; - -template<> struct size_to_precision<16> -{ - typedef extended_double_precision_tag type; -}; - -// fp_traits is a type switch that selects the right fp_traits_impl - -template<class T> struct fp_traits -{ - BOOST_STATIC_ASSERT(boost::is_floating_point<T>::value); - typedef BOOST_DEDUCED_TYPENAME size_to_precision<sizeof(T)>::type precision; - typedef fp_traits_impl<T, precision> type; -}; - - -//------------------------------------------------------------------------------ - -} // namespace detail -} // namespace math -} // namespace spirit -} // namespace boost - -#endif |