numerics.ipp

来自「CGAL is a collaborative effort of severa」· IPP 代码 · 共 533 行 · 第 1/2 页

IPP
533
字号
/*=============================================================================    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 <cmath>#if defined(BOOST_NO_STDC_NAMESPACE)#  define BOOST_SPIRIT_IMPL_STD_NS#else#  define BOOST_SPIRIT_IMPL_STD_NS std#endifnamespace boost { namespace spirit {    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        //        //      Test the validity of a single character:        //        //          template<typename CharT> static bool is_valid(CharT ch);        //        //      Convert a digit from character representation to binary        //      representation:        //        //          template<typename CharT> static int digit(CharT ch);        //        ///////////////////////////////////////////////////////////////////////        template<const int Radix>        struct radix_traits;        ////////////////////////////////// Binary        template<>        struct radix_traits<2>        {            template<typename CharT>            static bool is_valid(CharT ch)            {                return ('0' == ch || '1' == ch);            }            template<typename CharT>            static int digit(CharT ch)            {                return ch - '0';            }        };        ////////////////////////////////// Octal        template<>        struct radix_traits<8>        {            template<typename CharT>            static bool is_valid(CharT ch)            {                return ('0' <= ch && ch <= '7');            }            template<typename CharT>            static int digit(CharT ch)            {                return ch - '0';            }        };        ////////////////////////////////// Decimal        template<>        struct radix_traits<10>        {            template<typename CharT>            static bool is_valid(CharT ch)            {                return impl::isdigit_(ch);            }            template<typename CharT>            static int digit(CharT ch)            {                return ch - '0';            }        };        ////////////////////////////////// Hexadecimal        template<>        struct radix_traits<16>        {            template<typename CharT>            static bool is_valid(CharT ch)            {                return impl::isxdigit_(ch);            }            template<typename CharT>            static int digit(CharT ch)            {                if (impl::isdigit_(ch))                    return ch - '0';                return impl::tolower_(ch) - 'a' + 10;            }        };        ///////////////////////////////////////////////////////////////////////        //        //      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.        //        //          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 integral type.        //              Overflow (or underflow) is detected when an        //              operation wraps a value from its maximum to its        //              minimum (or vice-versa). For example, overflow        //              occurs when the result of the expression n * x is        //              less than n (assuming n is positive and x is        //              greater than 1).        //        //      BEWARE:        //              the parameters 'n' and 'count' should be properly        //              initialized before calling this function.        //        ///////////////////////////////////////////////////////////////////////        template <int Radix>        struct positive_accumulate        {            //  Use this accumulator if number is positive            template <typename T>            static bool check(T const& n, T const& prev)            {                return n < prev;            }            template <typename T, typename CharT>            static void add(T& n, CharT ch)            {                n += radix_traits<Radix>::digit(ch);            }        };        template <int Radix>        struct negative_accumulate        {            //  Use this accumulator if number is negative            template <typename T>            static bool check(T const& n, T const& prev)            {                return n > prev;            }            template <typename T, typename CharT>            static void add(T& n, CharT ch)            {                n -= radix_traits<Radix>::digit(ch);            }        };        template <int Radix, typename Accumulate>        struct extract_int_base        {            //  Common code for extract_int specializations            template <typename ScannerT, typename T>            static bool            f(ScannerT& scan, T& n)            {                T prev = n;                n *= Radix;                if (Accumulate::check(n, prev))                    return false;   //  over/underflow!                prev = n;                Accumulate::add(n, *scan);                if (Accumulate::check(n, prev))                    return false;   //  over/underflow!                return true;            }        };        template <bool Bounded>        struct extract_int_        {            template <                int Radix,                unsigned MinDigits,                int MaxDigits,                typename Accumulate            >            struct apply            {                typedef extract_int_base<Radix, Accumulate> base;                typedef radix_traits<Radix> check;                template <typename ScannerT, typename T>                static bool                f(ScannerT& scan, T& n, std::size_t& count)                {                    std::size_t i = 0;                    for (; (i < MaxDigits) && !scan.at_end()                        && check::is_valid(*scan);                        ++i, ++scan, ++count)                    {                        if (!base::f(scan, n))                            return false;   //  over/underflow!                    }                    return i >= MinDigits;                }            };        };        template <>        struct extract_int_<false>        {            template <

⌨️ 快捷键说明

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