⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fp_traits.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 2 页
字号:
// fp_traits.hpp#ifndef BOOST_MATH_FP_TRAITS_HPP#define BOOST_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#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 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 implementedboth 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 URequirements:   T = float, double or long double  U = single_precision_tag, double_precision_tag      or extended_double_precision_tagTypedef 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);                    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};//..............................................................................#elsetemplate<> 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -