numerics.ipp

来自「Boost provides free peer-reviewed portab」· IPP 代码 · 共 479 行 · 第 1/2 页

IPP
479
字号
/*=============================================================================    Copyright (c) 1998-2003 Joel de Guzman    Copyright (c) 2001-2003 Hartmut Kaiser    http://spirit.sourceforge.net/    Use, modification and distribution is subject to 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)=============================================================================*/#ifndef BOOST_SPIRIT_NUMERICS_IPP#define BOOST_SPIRIT_NUMERICS_IPP#include <boost/config/no_tr1/cmath.hpp>#include <limits>namespace boost { namespace spirit {BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN    struct sign_parser; // forward declaration only    namespace impl    {        ///////////////////////////////////////////////////////////////////////        //        //  Extract the prefix sign (- or +)        //        ///////////////////////////////////////////////////////////////////////        template <typename ScannerT>        bool        extract_sign(ScannerT const& scan, std::size_t& count)        {            //  Extract the sign            count = 0;            bool neg = *scan == '-';            if (neg || (*scan == '+'))            {                ++scan;                ++count;                return neg;            }            return false;        }        ///////////////////////////////////////////////////////////////////////        //        //  Traits class for radix specific number conversion        //        //      Convert a digit from character representation, ch, to binary        //      representation, returned in val.        //      Returns whether the conversion was successful.        //        //        template<typename CharT> static bool digit(CharT ch, T& val);        //        ///////////////////////////////////////////////////////////////////////        template<const int Radix>        struct radix_traits;        ////////////////////////////////// Binary        template<>        struct radix_traits<2>        {            template<typename CharT, typename T>            static bool digit(CharT ch, T& val)            {                val = ch - '0';                return ('0' == ch || '1' == ch);            }        };        ////////////////////////////////// Octal        template<>        struct radix_traits<8>        {            template<typename CharT, typename T>            static bool digit(CharT ch, T& val)            {                val = ch - '0';                return ('0' <= ch && ch <= '7');            }        };        ////////////////////////////////// Decimal        template<>        struct radix_traits<10>        {            template<typename CharT, typename T>            static bool digit(CharT ch, T& val)            {                val = ch - '0';                return impl::isdigit_(ch);            }        };        ////////////////////////////////// Hexadecimal        template<>        struct radix_traits<16>        {            template<typename CharT, typename T>            static bool digit(CharT ch, T& val)            {                if (radix_traits<10>::digit(ch, val))                    return true;                CharT lc = impl::tolower_(ch);                if ('a' <= lc && lc <= 'f')                {                    val = lc - 'a' + 10;                    return true;                }                return false;            }        };        ///////////////////////////////////////////////////////////////////////        //        //      Helper templates for encapsulation of radix specific        //      conversion of an input string to an integral value.        //        //      main entry point:        //        //          extract_int<Radix, MinDigits, MaxDigits, Accumulate>        //              ::f(first, last, n, count);        //        //          The template parameter Radix represents the radix of the        //          number contained in the parsed string. The template        //          parameter MinDigits specifies the minimum digits to        //          accept. The template parameter MaxDigits specifies the        //          maximum digits to parse. A -1 value for MaxDigits will        //          make it parse an arbitrarilly large number as long as the        //          numeric type can hold it. Accumulate is either        //          positive_accumulate<Radix> (default) for parsing positive        //          numbers or negative_accumulate<Radix> otherwise.        //          Checking is only performed when std::numeric_limits<T>::        //          is_specialized is true. Otherwise, there's no way to        //          do the check.        //        //          scan.first and scan.last are iterators as usual (i.e.        //          first is mutable and is moved forward when a match is        //          found), n is a variable that holds the number (passed by        //          reference). The number of parsed characters is added to        //          count (also passed by reference)        //        //      NOTE:        //              Returns a non-match, if the number to parse        //              overflows (or underflows) the used type.        //        //      BEWARE:        //              the parameters 'n' and 'count' should be properly        //              initialized before calling this function.        //        ///////////////////////////////////////////////////////////////////////        template <typename T, int Radix>        struct positive_accumulate        {            //  Use this accumulator if number is positive            static bool add(T& n, T digit)            {                if (std::numeric_limits<T>::is_specialized)                {                    static T const max = (std::numeric_limits<T>::max)();                    static T const max_div_radix = max/Radix;                    if (n > max_div_radix)                        return false;                    n *= Radix;                    if (n > max - digit)                        return false;                    n += digit;                    return true;                }                else                {                    n *= Radix;                    n += digit;                    return true;                }            }        };        template <typename T, int Radix>        struct negative_accumulate        {            //  Use this accumulator if number is negative            static bool add(T& n, T digit)            {                if (std::numeric_limits<T>::is_specialized)                {                    typedef std::numeric_limits<T> num_limits;                    static T const min =                        (!num_limits::is_integer && num_limits::is_signed && num_limits::has_denorm) ?                        -(num_limits::max)() : (num_limits::min)();                    static T const min_div_radix = min/Radix;                    if (n < min_div_radix)                        return false;                    n *= Radix;                    if (n < min + digit)                        return false;                    n -= digit;                    return true;                }                else                {                    n *= Radix;                    n -= digit;                    return true;                }            }        };        template <int MaxDigits>        inline bool allow_more_digits(std::size_t i)        {            return i < MaxDigits;        }        template <>        inline bool allow_more_digits<-1>(std::size_t)        {            return true;        }        //////////////////////////////////        template <            int Radix, unsigned MinDigits, int MaxDigits,            typename Accumulate        >        struct extract_int        {            template <typename ScannerT, typename T>            static bool            f(ScannerT& scan, T& n, std::size_t& count)            {                std::size_t i = 0;

⌨️ 快捷键说明

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