diff options
Diffstat (limited to 'boost/spirit/home/x3/support/numeric_utils')
5 files changed, 1094 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp b/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp new file mode 100644 index 0000000000..73770c87d0 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp @@ -0,0 +1,512 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2011 Jan Frederick Eick + Copyright (c) 2011 Christopher Jefferson + Copyright (c) 2006 Stephen Nutt + + 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(BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM) +#define BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/attribute_type.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp> +#include <boost/spirit/home/support/char_encoding/ascii.hpp> + +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/iteration/local.hpp> +#include <boost/preprocessor/comparison/less.hpp> +#include <boost/preprocessor/control/if.hpp> +#include <boost/preprocessor/seq/elem.hpp> + +#include <boost/detail/iterator.hpp> +#include <boost/utility/enable_if.hpp> + +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/make_unsigned.hpp> + +#include <boost/mpl/bool.hpp> +#include <boost/mpl/and.hpp> +#include <boost/limits.hpp> + +#if !defined(SPIRIT_NUMERICS_LOOP_UNROLL) +# define SPIRIT_NUMERICS_LOOP_UNROLL 3 +#endif + +namespace boost { namespace spirit { namespace x3 { namespace detail +{ + /////////////////////////////////////////////////////////////////////////// + // + // The maximum radix digits that can be represented without + // overflow: + // + // template<typename T, unsigned Radix> + // struct digits_traits::value; + // + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix> + struct digits_traits; + +// lookup table for log2(x) : 2 <= x <= 36 +#define BOOST_SPIRIT_X3_LOG2 (#error)(#error) \ + (1000000)(1584960)(2000000)(2321920)(2584960)(2807350) \ + (3000000)(3169920)(3321920)(3459430)(3584960)(3700430) \ + (3807350)(3906890)(4000000)(4087460)(4169920)(4247920) \ + (4321920)(4392310)(4459430)(4523560)(4584960)(4643850) \ + (4700430)(4754880)(4807350)(4857980)(4906890)(4954190) \ + (5000000)(5044390)(5087460)(5129280)(5169925) \ + /***/ + +#define BOOST_PP_LOCAL_MACRO(Radix) \ + template <typename T> struct digits_traits<T, Radix> \ + { \ + typedef std::numeric_limits<T> numeric_limits_type; \ + BOOST_STATIC_CONSTANT(int, value = static_cast<int>( \ + (numeric_limits_type::digits * 1000000) / \ + BOOST_PP_SEQ_ELEM(Radix, BOOST_SPIRIT_X3_LOG2))); \ + }; \ + /***/ + +#define BOOST_PP_LOCAL_LIMITS (2, 36) +#include BOOST_PP_LOCAL_ITERATE() + +#undef BOOST_SPIRIT_X3_LOG2 + + /////////////////////////////////////////////////////////////////////////// + // + // Traits class for radix specific number conversion + // + // Test the validity of a single character: + // + // template<typename Char> static bool is_valid(Char ch); + // + // Convert a digit from character representation to binary + // representation: + // + // template<typename Char> static int digit(Char ch); + // + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix> + struct radix_traits + { + template <typename Char> + inline static bool is_valid(Char ch) + { + if (Radix <= 10) + return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1)); + return (ch >= '0' && ch <= '9') + || (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1)) + || (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1)); + } + + template <typename Char> + inline static unsigned digit(Char ch) + { + if (Radix <= 10 || (ch >= '0' && ch <= '9')) + return ch - '0'; + return char_encoding::ascii::tolower(ch) - 'a' + 10; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // positive_accumulator/negative_accumulator: Accumulator policies for + // extracting integers. Use positive_accumulator if number is positive. + // Use negative_accumulator if number is negative. + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix> + struct positive_accumulator + { + template <typename T, typename Char> + inline static void add(T& n, Char ch, mpl::false_) // unchecked add + { + const int digit = radix_traits<Radix>::digit(ch); + n = n * T(Radix) + T(digit); + } + + template <typename T, typename Char> + inline static bool add(T& n, Char ch, mpl::true_) // checked add + { + // Ensure n *= Radix will not overflow + static T const max = (std::numeric_limits<T>::max)(); + static T const val = max / Radix; + if (n > val) + return false; + + n *= Radix; + + // Ensure n += digit will not overflow + const int digit = radix_traits<Radix>::digit(ch); + if (n > max - digit) + return false; + + n += static_cast<T>(digit); + return true; + } + }; + + template <unsigned Radix> + struct negative_accumulator + { + template <typename T, typename Char> + inline static void add(T& n, Char ch, mpl::false_) // unchecked subtract + { + const int digit = radix_traits<Radix>::digit(ch); + n = n * T(Radix) - T(digit); + } + + template <typename T, typename Char> + inline static bool add(T& n, Char ch, mpl::true_) // checked subtract + { + // Ensure n *= Radix will not underflow + static T const min = (std::numeric_limits<T>::min)(); + static T const val = (min + 1) / T(Radix); + if (n < val) + return false; + + n *= Radix; + + // Ensure n -= digit will not underflow + int const digit = radix_traits<Radix>::digit(ch); + if (n < min + digit) + return false; + + n -= static_cast<T>(digit); + return true; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // Common code for extract_int::parse specializations + /////////////////////////////////////////////////////////////////////////// + template <unsigned Radix, typename Accumulator, int MaxDigits> + struct int_extractor + { + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t count, T& n, mpl::true_) + { + static std::size_t const + overflow_free = digits_traits<T, Radix>::value - 1; + + if (count < overflow_free) + { + Accumulator::add(n, ch, mpl::false_()); + } + else + { + if (!Accumulator::add(n, ch, mpl::true_())) + return false; // over/underflow! + } + return true; + } + + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t /*count*/, T& n, mpl::false_) + { + // no need to check for overflow + Accumulator::add(n, ch, mpl::false_()); + return true; + } + + template <typename Char> + inline static bool + call(Char /*ch*/, std::size_t /*count*/, unused_type, mpl::false_) + { + return true; + } + + template <typename Char, typename T> + inline static bool + call(Char ch, std::size_t count, T& n) + { + return call(ch, count, n + , mpl::bool_< + ( (MaxDigits < 0) + || (MaxDigits > digits_traits<T, Radix>::value) + ) + && traits::check_overflow<T>::value + >() + ); + } + }; + + /////////////////////////////////////////////////////////////////////////// + // End of loop checking: check if the number of digits + // being parsed exceeds MaxDigits. Note: if MaxDigits == -1 + // we don't do any checking. + /////////////////////////////////////////////////////////////////////////// + template <int MaxDigits> + struct check_max_digits + { + inline static bool + call(std::size_t count) + { + return count < MaxDigits; // bounded + } + }; + + template <> + struct check_max_digits<-1> + { + inline static bool + call(std::size_t /*count*/) + { + return true; // unbounded + } + }; + + /////////////////////////////////////////////////////////////////////////// + // extract_int: main code for extracting integers + /////////////////////////////////////////////////////////////////////////// +#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + if (!check_max_digits<MaxDigits>::call(count + leading_zeros) \ + || it == last) \ + break; \ + ch = *it; \ + if (!radix_check::is_valid(ch) || !extractor::call(ch, count, val)) \ + break; \ + ++it; \ + ++count; \ + /**/ + + template < + typename T, unsigned Radix, unsigned MinDigits, int MaxDigits + , typename Accumulator = positive_accumulator<Radix> + , bool Accumulate = false + > + struct extract_int + { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + template <typename Iterator, typename Attribute> + inline static bool + parse_main( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + typedef radix_traits<Radix> radix_check; + typedef int_extractor<Radix, Accumulator, MaxDigits> extractor; + typedef typename + boost::detail::iterator_traits<Iterator>::value_type + char_type; + + Iterator it = first; + std::size_t leading_zeros = 0; + if (!Accumulate) + { + // skip leading zeros + while (it != last && *it == '0' && leading_zeros < MaxDigits) + { + ++it; + ++leading_zeros; + } + } + + typedef typename + traits::attribute_type<Attribute>::type + attribute_type; + + attribute_type val = Accumulate ? attr : attribute_type(0); + std::size_t count = 0; + char_type ch; + + while (true) + { + BOOST_PP_REPEAT( + SPIRIT_NUMERICS_LOOP_UNROLL + , SPIRIT_NUMERIC_INNER_LOOP, _) + } + + if (count + leading_zeros >= MinDigits) + { + traits::move_to(val, attr); + first = it; + return true; + } + return false; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + + template <typename Iterator> + inline static bool + parse( + Iterator& first + , Iterator const& last + , unused_type) + { + T n = 0; // must calculate value to detect over/underflow + return parse_main(first, last, n); + } + + template <typename Iterator, typename Attribute> + inline static bool + parse( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + return parse_main(first, last, attr); + } + }; +#undef SPIRIT_NUMERIC_INNER_LOOP + + /////////////////////////////////////////////////////////////////////////// + // extract_int: main code for extracting integers + // common case where MinDigits == 1 and MaxDigits = -1 + /////////////////////////////////////////////////////////////////////////// +#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + if (it == last) \ + break; \ + ch = *it; \ + if (!radix_check::is_valid(ch)) \ + break; \ + if (!extractor::call(ch, count, val)) \ + return false; \ + ++it; \ + ++count; \ + /**/ + + template <typename T, unsigned Radix, typename Accumulator, bool Accumulate> + struct extract_int<T, Radix, 1, -1, Accumulator, Accumulate> + { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + template <typename Iterator, typename Attribute> + inline static bool + parse_main( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + typedef radix_traits<Radix> radix_check; + typedef int_extractor<Radix, Accumulator, -1> extractor; + typedef typename + boost::detail::iterator_traits<Iterator>::value_type + char_type; + + Iterator it = first; + std::size_t count = 0; + if (!Accumulate) + { + // skip leading zeros + while (it != last && *it == '0') + { + ++it; + ++count; + } + + if (it == last) + { + if (count == 0) // must have at least one digit + return false; + attr = 0; + first = it; + return true; + } + } + + typedef typename + traits::attribute_type<Attribute>::type + attribute_type; + + attribute_type val = Accumulate ? attr : attribute_type(0); + char_type ch = *it; + + if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val)) + { + if (count == 0) // must have at least one digit + return false; + traits::move_to(val, attr); + first = it; + return true; + } + + count = 0; + ++it; + while (true) + { + BOOST_PP_REPEAT( + SPIRIT_NUMERICS_LOOP_UNROLL + , SPIRIT_NUMERIC_INNER_LOOP, _) + } + + traits::move_to(val, attr); + first = it; + return true; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + + template <typename Iterator> + inline static bool + parse( + Iterator& first + , Iterator const& last + , unused_type) + { + T n = 0; // must calculate value to detect over/underflow + return parse_main(first, last, n); + } + + template <typename Iterator, typename Attribute> + inline static bool + parse( + Iterator& first + , Iterator const& last + , Attribute& attr) + { + return parse_main(first, last, attr); + } + }; + +#undef SPIRIT_NUMERIC_INNER_LOOP + + /////////////////////////////////////////////////////////////////////////// + // Cast an signed integer to an unsigned integer + /////////////////////////////////////////////////////////////////////////// + template <typename T, + bool force_unsigned + = mpl::and_<is_integral<T>, is_signed<T> >::value> + struct cast_unsigned; + + template <typename T> + struct cast_unsigned<T, true> + { + typedef typename make_unsigned<T>::type unsigned_type; + typedef typename make_unsigned<T>::type& unsigned_type_ref; + + inline static unsigned_type_ref call(T& n) + { + return unsigned_type_ref(n); + } + }; + + template <typename T> + struct cast_unsigned<T, false> + { + inline static T& call(T& n) + { + return n; + } + }; +}}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp b/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp new file mode 100644 index 0000000000..aa80cdd6ea --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp @@ -0,0 +1,147 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2011 Jan Frederick Eick + + 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(BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM) +#define BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp> +#include <boost/assert.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + /////////////////////////////////////////////////////////////////////////// + // Extract the prefix sign (- or +), return true if a '-' was found + /////////////////////////////////////////////////////////////////////////// + template <typename Iterator> + inline bool + extract_sign(Iterator& first, Iterator const& last) + { + (void)last; // silence unused warnings + BOOST_ASSERT(first != last); // precondition + + // Extract the sign + bool neg = *first == '-'; + if (neg || (*first == '+')) + { + ++first; + return neg; + } + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Low level unsigned integer parser + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits + , bool Accumulate = false> + struct extract_uint + { + // check template parameter 'Radix' for validity + static_assert( + (Radix >= 2 && Radix <= 36), + "Error Unsupported Radix"); + + template <typename Iterator> + inline static bool call(Iterator& first, Iterator const& last, T& attr) + { + if (first == last) + return false; + + typedef detail::extract_int< + T + , Radix + , MinDigits + , MaxDigits + , detail::positive_accumulator<Radix> + , Accumulate> + extract_type; + + Iterator save = first; + if (!extract_type::parse(first, last, + detail::cast_unsigned<T>::call(attr))) + { + first = save; + return false; + } + return true; + } + + template <typename Iterator, typename Attribute> + inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + { + // this case is called when Attribute is not T + T attr; + if (call(first, last, attr)) + { + traits::move_to(attr, attr_); + return true; + } + return false; + } + }; + + /////////////////////////////////////////////////////////////////////////// + // Low level signed integer parser + /////////////////////////////////////////////////////////////////////////// + template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits> + struct extract_int + { + // check template parameter 'Radix' for validity + static_assert( + (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16), + "Error Unsupported Radix"); + + template <typename Iterator> + inline static bool call(Iterator& first, Iterator const& last, T& attr) + { + if (first == last) + return false; + + typedef detail::extract_int< + T, Radix, MinDigits, MaxDigits> + extract_pos_type; + + typedef detail::extract_int< + T, Radix, MinDigits, MaxDigits, detail::negative_accumulator<Radix> > + extract_neg_type; + + Iterator save = first; + bool hit = extract_sign(first, last); + if (hit) + hit = extract_neg_type::parse(first, last, attr); + else + hit = extract_pos_type::parse(first, last, attr); + + if (!hit) + { + first = save; + return false; + } + return true; + } + + template <typename Iterator, typename Attribute> + inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + { + // this case is called when Attribute is not T + T attr; + if (call(first, last, attr)) + { + traits::move_to(attr, attr_); + return true; + } + return false; + } + }; +}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp new file mode 100644 index 0000000000..fb30f02306 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp @@ -0,0 +1,271 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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(SPIRIT_EXTRACT_REAL_APRIL_18_2006_0901AM) +#define SPIRIT_EXTRACT_REAL_APRIL_18_2006_0901AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <cmath> +#include <boost/limits.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/pow10.hpp> +#include <boost/spirit/home/x3/support/numeric_utils/sign.hpp> +#include <boost/spirit/home/x3/support/traits/move_to.hpp> +#include <boost/assert.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4100) // 'p': unreferenced formal parameter +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace spirit { namespace x3 { namespace extension +{ + using x3::traits::pow10; + + template <typename T> + inline void + scale(int exp, T& n) + { + if (exp >= 0) + { + // $$$ Why is this failing for boost.math.concepts ? $$$ + //~ int nn = std::numeric_limits<T>::max_exponent10; + //~ BOOST_ASSERT(exp <= std::numeric_limits<T>::max_exponent10); + n *= pow10<T>(exp); + } + else + { + if (exp < std::numeric_limits<T>::min_exponent10) + { + n /= pow10<T>(-std::numeric_limits<T>::min_exponent10); + n /= pow10<T>(-exp + std::numeric_limits<T>::min_exponent10); + } + else + { + n /= pow10<T>(-exp); + } + } + } + + inline void + scale(int /*exp*/, unused_type /*n*/) + { + // no-op for unused_type + } + + template <typename T> + inline void + scale(int exp, int frac, T& n) + { + scale(exp - frac, n); + } + + inline void + scale(int /*exp*/, int /*frac*/, unused_type /*n*/) + { + // no-op for unused_type + } + + inline float + negate(bool neg, float n) + { + return neg ? x3::changesign(n) : n; + } + + inline double + negate(bool neg, double n) + { + return neg ? x3::changesign(n) : n; + } + + inline long double + negate(bool neg, long double n) + { + return neg ? x3::changesign(n) : n; + } + + template <typename T> + inline T + negate(bool neg, T const& n) + { + return neg ? -n : n; + } + + inline unused_type + negate(bool /*neg*/, unused_type n) + { + // no-op for unused_type + return n; + } + + template <typename T> + inline bool + is_equal_to_one(T const& value) + { + return value == 1.0; + } + + inline bool + is_equal_to_one(unused_type) + { + // no-op for unused_type + return false; + } +}}}} + +namespace boost { namespace spirit { namespace x3 +{ + template <typename T, typename RealPolicies> + struct extract_real + { + template <typename Iterator, typename Attribute> + static bool + parse(Iterator& first, Iterator const& last, Attribute& attr, + RealPolicies const& p) + { + if (first == last) + return false; + Iterator save = first; + + // Start by parsing the sign. neg will be true if + // we got a "-" sign, false otherwise. + bool neg = p.parse_sign(first, last); + + // Now attempt to parse an integer + T n = 0; + bool got_a_number = p.parse_n(first, last, n); + + // If we did not get a number it might be a NaN, Inf or a leading + // dot. + if (!got_a_number) + { + // Check whether the number to parse is a NaN or Inf + if (p.parse_nan(first, last, n) || + p.parse_inf(first, last, n)) + { + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + return true; // got a NaN or Inf, return early + } + + // If we did not get a number and our policies do not + // allow a leading dot, fail and return early (no-match) + if (!p.allow_leading_dot) + { + first = save; + return false; + } + } + + bool e_hit = false; + int frac_digits = 0; + + // Try to parse the dot ('.' decimal point) + if (p.parse_dot(first, last)) + { + // We got the decimal point. Now we will try to parse + // the fraction if it is there. If not, it defaults + // to zero (0) only if we already got a number. + Iterator savef = first; + if (p.parse_frac_n(first, last, n)) + { + // Optimization note: don't compute frac_digits if T is + // an unused_type. This should be optimized away by the compiler. + if (!is_same<T, unused_type>::value) + frac_digits = + static_cast<int>(std::distance(savef, first)); + } + else if (!got_a_number || !p.allow_trailing_dot) + { + // We did not get a fraction. If we still haven't got a + // number and our policies do not allow a trailing dot, + // return no-match. + first = save; + return false; + } + + // Now, let's see if we can parse the exponent prefix + e_hit = p.parse_exp(first, last); + } + else + { + // No dot and no number! Return no-match. + if (!got_a_number) + { + first = save; + return false; + } + + // If we must expect a dot and we didn't see an exponent + // prefix, return no-match. + e_hit = p.parse_exp(first, last); + if (p.expect_dot && !e_hit) + { + first = save; + return false; + } + } + + if (e_hit) + { + // We got the exponent prefix. Now we will try to parse the + // actual exponent. It is an error if it is not there. + int exp = 0; + if (p.parse_exp_n(first, last, exp)) + { + // Got the exponent value. Scale the number by + // exp-frac_digits. + extension::scale(exp, frac_digits, n); + } + else + { + // Oops, no exponent, return no-match. + first = save; + return false; + } + } + else if (frac_digits) + { + // No exponent found. Scale the number by -frac_digits. + extension::scale(-frac_digits, n); + } + else if (extension::is_equal_to_one(n)) + { + // There is a chance of having to parse one of the 1.0#... + // styles some implementations use for representing NaN or Inf. + + // Check whether the number to parse is a NaN or Inf + if (p.parse_nan(first, last, n) || + p.parse_inf(first, last, n)) + { + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + return true; // got a NaN or Inf, return immediately + } + } + + // If we got a negative sign, negate the number + traits::move_to(extension::negate(neg, n), attr); + + // Success!!! + return true; + } + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +}}} + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/pow10.hpp b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp new file mode 100644 index 0000000000..f51d29fba8 --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/pow10.hpp @@ -0,0 +1,116 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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(BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM) +#define BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/limits.hpp> +#include <boost/spirit/home/x3/support/unused.hpp> +#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data +#endif + +namespace boost { namespace spirit { namespace x3 { namespace traits +{ + namespace detail + { + template <typename T, typename Enable = void> + struct pow10_helper + { + static T call(unsigned dim) + { + using namespace std; // allow for ADL to find the correct overload + return pow(T(10), T(dim)); + } + }; + + template <> + struct pow10_helper<unused_type> + { + static unused_type call(unused_type) + { + return unused; + } + }; + +#if (DBL_MAX_10_EXP == 308) // for IEEE-754 + template <> + struct pow10_helper<double> + { + static double call(unsigned dim) + { + static double const exponents[] = + { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, + 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, + 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, + 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, + 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, + 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, + 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, + 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308, + }; + BOOST_ASSERT(dim < sizeof(exponents)/sizeof(double)); + return exponents[dim]; + } + }; + + template <> + struct pow10_helper<float> + { + static float call(unsigned dim) + { + return pow10_helper<double>::call(dim); + } + }; +#endif // for IEEE-754 + } + + template <typename T> + inline T pow10(unsigned dim) + { + return detail::pow10_helper<T>::call(dim); + } +}}}} + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +#endif diff --git a/boost/spirit/home/x3/support/numeric_utils/sign.hpp b/boost/spirit/home/x3/support/numeric_utils/sign.hpp new file mode 100644 index 0000000000..fe2feceeed --- /dev/null +++ b/boost/spirit/home/x3/support/numeric_utils/sign.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2001-2011 Hartmut Kaiser + http://spirit.sourceforge.net/ + + 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(SPIRIT_SIGN_MAR_11_2009_0734PM) +#define SPIRIT_SIGN_MAR_11_2009_0734PM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/math/special_functions/sign.hpp> + +namespace boost { namespace spirit { namespace x3 +{ + template<typename T> + inline bool (signbit)(T x) + { + return (boost::math::signbit)(x) ? true : false; + } + + // This routine has been taken and adapted from Johan Rade's fp_traits + // library + template<typename T> + inline T (changesign)(T x) + { +#if defined(BOOST_MATH_USE_STD_FPCLASSIFY) && !defined(BOOST_MATH_DISABLE_STD_FPCLASSIFY) + return -x; +#else + typedef typename math::detail::fp_traits<T>::type traits_type; + + typename traits_type::bits a; + traits_type::get_bits(x, a); + a ^= traits_type::sign; + traits_type::set_bits(x, a); + return x; +#endif + } + +}}} + +#endif |