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 + -
显示快捷键?