Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:38

0001 /*=============================================================================
0002     Copyright (c) 2001-2014 Joel de Guzman
0003     Copyright (c) 2001-2011 Hartmut Kaiser
0004     http://spirit.sourceforge.net/
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 =============================================================================*/
0009 #if !defined(BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM)
0010 #define BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM
0011 
0012 #include <cmath>
0013 #include <boost/limits.hpp>
0014 #include <boost/type_traits/is_same.hpp>
0015 #include <boost/spirit/home/x3/support/unused.hpp>
0016 #include <boost/spirit/home/x3/support/numeric_utils/pow10.hpp>
0017 #include <boost/spirit/home/x3/support/traits/move_to.hpp>
0018 #include <boost/assert.hpp>
0019 
0020 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0021 # pragma warning(push)
0022 # pragma warning(disable: 4100)   // 'p': unreferenced formal parameter
0023 # pragma warning(disable: 4127)   // conditional expression is constant
0024 #endif
0025 
0026 namespace boost { namespace spirit { namespace x3 { namespace extension
0027 {
0028     using x3::traits::pow10;
0029 
0030     template <typename T>
0031     inline bool
0032     scale(int exp, T& n)
0033     {
0034         constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
0035         constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
0036 
0037         if (exp >= 0)
0038         {
0039             // return false if exp exceeds the max_exp
0040             // do this check only for primitive types!
0041             if (is_floating_point<T>() && exp > max_exp)
0042                 return false;
0043             n *= pow10<T>(exp);
0044         }
0045         else
0046         {
0047             if (exp < min_exp)
0048             {
0049                 n /= pow10<T>(-min_exp);
0050 
0051                 // return false if exp still exceeds the min_exp
0052                 // do this check only for primitive types!
0053                 exp += -min_exp;
0054                 if (is_floating_point<T>() && exp < min_exp)
0055                     return false;
0056 
0057                 n /= pow10<T>(-exp);
0058             }
0059             else
0060             {
0061                 n /= pow10<T>(-exp);
0062             }
0063         }
0064         return true;
0065     }
0066 
0067     inline bool
0068     scale(int /*exp*/, unused_type /*n*/)
0069     {
0070         // no-op for unused_type
0071         return true;
0072     }
0073 
0074     template <typename T>
0075     inline bool
0076     scale(int exp, int frac, T& n)
0077     {
0078         return scale(exp - frac, n);
0079     }
0080 
0081     inline bool
0082     scale(int /*exp*/, int /*frac*/, unused_type /*n*/)
0083     {
0084         // no-op for unused_type
0085         return true;
0086     }
0087 
0088     inline float
0089     negate(bool neg, float n)
0090     {
0091         return neg ? (std::copysignf)(n, -1.f) : n;
0092     }
0093 
0094     inline double
0095     negate(bool neg, double n)
0096     {
0097         return neg ? (std::copysign)(n, -1.) : n;
0098     }
0099 
0100     inline long double
0101     negate(bool neg, long double n)
0102     {
0103         return neg ? (std::copysignl)(n, -1.) : n;
0104     }
0105 
0106     template <typename T>
0107     inline T
0108     negate(bool neg, T const& n)
0109     {
0110         return neg ? -n : n;
0111     }
0112 
0113     inline unused_type
0114     negate(bool /*neg*/, unused_type n)
0115     {
0116         // no-op for unused_type
0117         return n;
0118     }
0119 }}}}
0120 
0121 namespace boost { namespace spirit { namespace x3
0122 {
0123     template <typename T, typename RealPolicies>
0124     struct extract_real
0125     {
0126         template <typename Iterator, typename Attribute>
0127         static bool
0128         parse(Iterator& first, Iterator const& last, Attribute& attr,
0129             RealPolicies const& p)
0130         {
0131             if (first == last)
0132                 return false;
0133             Iterator save = first;
0134 
0135             // Start by parsing the sign. neg will be true if
0136             // we got a "-" sign, false otherwise.
0137             bool neg = p.parse_sign(first, last);
0138 
0139             // Now attempt to parse an integer
0140             T n = 0;
0141             bool got_a_number = p.parse_n(first, last, n);
0142 
0143             // If we did not get a number it might be a NaN, Inf or a leading
0144             // dot.
0145             if (!got_a_number)
0146             {
0147                 // Check whether the number to parse is a NaN or Inf
0148                 if (p.parse_nan(first, last, n) ||
0149                     p.parse_inf(first, last, n))
0150                 {
0151                     // If we got a negative sign, negate the number
0152                     traits::move_to(extension::negate(neg, n), attr);
0153                     return true;    // got a NaN or Inf, return early
0154                 }
0155 
0156                 // If we did not get a number and our policies do not
0157                 // allow a leading dot, fail and return early (no-match)
0158                 if (!p.allow_leading_dot)
0159                 {
0160                     first = save;
0161                     return false;
0162                 }
0163             }
0164 
0165             bool e_hit = false;
0166             Iterator e_pos;
0167             int frac_digits = 0;
0168 
0169             // Try to parse the dot ('.' decimal point)
0170             if (p.parse_dot(first, last))
0171             {
0172                 // We got the decimal point. Now we will try to parse
0173                 // the fraction if it is there. If not, it defaults
0174                 // to zero (0) only if we already got a number.
0175                 Iterator savef = first;
0176                 if (p.parse_frac_n(first, last, n))
0177                 {
0178                     // Optimization note: don't compute frac_digits if T is
0179                     // an unused_type. This should be optimized away by the compiler.
0180                     if (!is_same<T, unused_type>::value)
0181                         frac_digits =
0182                             static_cast<int>(std::distance(savef, first));
0183                     BOOST_ASSERT(frac_digits >= 0);
0184                 }
0185                 else if (!got_a_number || !p.allow_trailing_dot)
0186                 {
0187                     // We did not get a fraction. If we still haven't got a
0188                     // number and our policies do not allow a trailing dot,
0189                     // return no-match.
0190                     first = save;
0191                     return false;
0192                 }
0193 
0194                 // Now, let's see if we can parse the exponent prefix
0195                 e_pos = first;
0196                 e_hit = p.parse_exp(first, last);
0197             }
0198             else
0199             {
0200                 // No dot and no number! Return no-match.
0201                 if (!got_a_number)
0202                 {
0203                     first = save;
0204                     return false;
0205                 }
0206 
0207                 // If we must expect a dot and we didn't see an exponent
0208                 // prefix, return no-match.
0209                 e_pos = first;
0210                 e_hit = p.parse_exp(first, last);
0211                 if (p.expect_dot && !e_hit)
0212                 {
0213                     first = save;
0214                     return false;
0215                 }
0216             }
0217 
0218             if (e_hit)
0219             {
0220                 // We got the exponent prefix. Now we will try to parse the
0221                 // actual exponent. It is an error if it is not there.
0222                 int exp = 0;
0223                 if (p.parse_exp_n(first, last, exp))
0224                 {
0225                     // Got the exponent value. Scale the number by
0226                     // exp-frac_digits.
0227                     if (!extension::scale(exp, frac_digits, n))
0228                         return false;
0229                 }
0230                 else
0231                 {
0232                     // If there is no number, disregard the exponent altogether.
0233                     // by resetting 'first' prior to the exponent prefix (e|E)
0234                     first = e_pos;
0235 
0236                     // Scale the number by -frac_digits.
0237                     if (!extension::scale(-frac_digits, n))
0238                         return false;
0239                 }
0240             }
0241             else if (frac_digits)
0242             {
0243                 // No exponent found. Scale the number by -frac_digits.
0244                 if (!extension::scale(-frac_digits, n))
0245                     return false;
0246             }
0247 
0248             // If we got a negative sign, negate the number
0249             traits::move_to(extension::negate(neg, n), attr);
0250 
0251             // Success!!!
0252             return true;
0253         }
0254     };
0255 
0256 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0257 # pragma warning(pop)
0258 #endif
0259 
0260 }}}
0261 
0262 #endif