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