File indexing completed on 2025-01-19 09:47:45
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_SPIRIT_QI_NUMERIC_DETAIL_REAL_IMPL_HPP
0010 #define BOOST_SPIRIT_QI_NUMERIC_DETAIL_REAL_IMPL_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <cmath>
0017 #include <boost/limits.hpp>
0018 #include <boost/type_traits/is_same.hpp>
0019 #include <boost/spirit/home/support/unused.hpp>
0020 #include <boost/spirit/home/qi/detail/attributes.hpp>
0021 #include <boost/spirit/home/support/detail/pow10.hpp>
0022 #include <boost/integer.hpp>
0023 #include <boost/assert.hpp>
0024
0025 #include <boost/core/cmath.hpp>
0026
0027 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0028 # pragma warning(push)
0029 # pragma warning(disable: 4100)
0030 # pragma warning(disable: 4127)
0031 #endif
0032
0033 namespace boost { namespace spirit { namespace traits
0034 {
0035 using spirit::traits::pow10;
0036
0037 namespace detail
0038 {
0039 template <typename T, typename AccT>
0040 void compensate_roundoff(T& n, AccT acc_n, mpl::true_)
0041 {
0042
0043
0044 int const comp = 10;
0045 n = T((acc_n / comp) * comp);
0046 n += T(acc_n % comp);
0047 }
0048
0049 template <typename T, typename AccT>
0050 void compensate_roundoff(T& n, AccT acc_n, mpl::false_)
0051 {
0052
0053 n = acc_n;
0054 }
0055
0056 template <typename T, typename AccT>
0057 void compensate_roundoff(T& n, AccT acc_n)
0058 {
0059 compensate_roundoff(n, acc_n, is_integral<AccT>());
0060 }
0061 }
0062
0063 template <typename T, typename AccT>
0064 inline bool
0065 scale(int exp, T& n, AccT acc_n)
0066 {
0067 if (exp >= 0)
0068 {
0069 int const max_exp = std::numeric_limits<T>::max_exponent10;
0070
0071
0072
0073 if (is_floating_point<T>() && (exp > max_exp))
0074 return false;
0075 n = acc_n * pow10<T>(exp);
0076 }
0077 else
0078 {
0079 if (exp < std::numeric_limits<T>::min_exponent10)
0080 {
0081 int const min_exp = std::numeric_limits<T>::min_exponent10;
0082 detail::compensate_roundoff(n, acc_n);
0083 n /= pow10<T>(-min_exp);
0084
0085
0086
0087 exp += -min_exp;
0088 if (is_floating_point<T>() && exp < min_exp)
0089 return false;
0090
0091 n /= pow10<T>(-exp);
0092 }
0093 else
0094 {
0095 n = T(acc_n) / pow10<T>(-exp);
0096 }
0097 }
0098 return true;
0099 }
0100
0101 inline bool
0102 scale(int , unused_type , unused_type )
0103 {
0104
0105 return true;
0106 }
0107
0108 template <typename T, typename AccT>
0109 inline bool
0110 scale(int exp, int frac, T& n, AccT acc_n)
0111 {
0112 return scale(exp - frac, n, acc_n);
0113 }
0114
0115 inline bool
0116 scale(int , int , unused_type )
0117 {
0118
0119 return true;
0120 }
0121
0122 inline float
0123 negate(bool neg, float n)
0124 {
0125 return neg ? (core::copysign)(n, -1.f) : n;
0126 }
0127
0128 inline double
0129 negate(bool neg, double n)
0130 {
0131 return neg ? (core::copysign)(n, -1.) : n;
0132 }
0133
0134 inline long double
0135 negate(bool neg, long double n)
0136 {
0137 return neg ? (core::copysign)(n, static_cast<long double>(-1)) : n;
0138 }
0139
0140 template <typename T>
0141 inline T
0142 negate(bool neg, T const& n)
0143 {
0144 return neg ? -n : n;
0145 }
0146
0147 inline unused_type
0148 negate(bool , unused_type n)
0149 {
0150
0151 return n;
0152 }
0153
0154 template <typename T>
0155 struct real_accumulator : mpl::identity<T> {};
0156
0157 template <>
0158 struct real_accumulator<float>
0159 : mpl::identity<uint_t<(sizeof(float)*CHAR_BIT)>::least> {};
0160
0161 template <>
0162 struct real_accumulator<double>
0163 : mpl::identity<uint_t<(sizeof(double)*CHAR_BIT)>::least> {};
0164 }}}
0165
0166 namespace boost { namespace spirit { namespace qi { namespace detail
0167 {
0168 BOOST_MPL_HAS_XXX_TRAIT_DEF(version)
0169
0170 template <typename T, typename RealPolicies>
0171 struct real_impl
0172 {
0173 template <typename Iterator>
0174 static std::size_t
0175 ignore_excess_digits(Iterator& , Iterator const& , mpl::false_)
0176 {
0177 return 0;
0178 }
0179
0180 template <typename Iterator>
0181 static std::size_t
0182 ignore_excess_digits(Iterator& first, Iterator const& last, mpl::true_)
0183 {
0184 return RealPolicies::ignore_excess_digits(first, last);
0185 }
0186
0187 template <typename Iterator>
0188 static std::size_t
0189 ignore_excess_digits(Iterator& first, Iterator const& last)
0190 {
0191 typedef mpl::bool_<has_version<RealPolicies>::value> has_version;
0192 return ignore_excess_digits(first, last, has_version());
0193 }
0194
0195 template <typename Iterator, typename Attribute>
0196 static bool
0197 parse(Iterator& first, Iterator const& last, Attribute& attr,
0198 RealPolicies const& p)
0199 {
0200 if (first == last)
0201 return false;
0202 Iterator save = first;
0203
0204
0205
0206 bool neg = p.parse_sign(first, last);
0207
0208
0209 T n;
0210
0211 typename traits::real_accumulator<T>::type acc_n = 0;
0212 bool got_a_number = p.parse_n(first, last, acc_n);
0213 int excess_n = 0;
0214
0215
0216
0217 if (!got_a_number)
0218 {
0219
0220 if (p.parse_nan(first, last, n) ||
0221 p.parse_inf(first, last, n))
0222 {
0223
0224 traits::assign_to(traits::negate(neg, n), attr);
0225 return true;
0226 }
0227
0228
0229
0230 if (!p.allow_leading_dot)
0231 {
0232 first = save;
0233 return false;
0234 }
0235 }
0236 else
0237 {
0238
0239
0240 excess_n = static_cast<int>(ignore_excess_digits(first, last));
0241 }
0242
0243 bool e_hit = false;
0244 Iterator e_pos;
0245 int frac_digits = 0;
0246
0247
0248 if (p.parse_dot(first, last))
0249 {
0250
0251
0252
0253 if (excess_n != 0)
0254 {
0255
0256 ignore_excess_digits(first, last);
0257 }
0258 else if (p.parse_frac_n(first, last, acc_n, frac_digits))
0259 {
0260 BOOST_ASSERT(frac_digits >= 0);
0261 }
0262 else if (!got_a_number || !p.allow_trailing_dot)
0263 {
0264
0265
0266
0267 first = save;
0268 return false;
0269 }
0270
0271
0272 e_pos = first;
0273 e_hit = p.parse_exp(first, last);
0274 }
0275 else
0276 {
0277
0278 if (!got_a_number)
0279 {
0280 first = save;
0281 return false;
0282 }
0283
0284
0285
0286 e_pos = first;
0287 e_hit = p.parse_exp(first, last);
0288 if (p.expect_dot && !e_hit)
0289 {
0290 first = save;
0291 return false;
0292 }
0293 }
0294
0295 if (e_hit)
0296 {
0297
0298
0299 int exp = 0;
0300 if (p.parse_exp_n(first, last, exp))
0301 {
0302
0303
0304 if (!traits::scale(exp + excess_n, frac_digits, n, acc_n))
0305 return false;
0306 }
0307 else
0308 {
0309
0310
0311 first = e_pos;
0312
0313 bool r = traits::scale(-frac_digits, n, acc_n);
0314 BOOST_VERIFY(r);
0315 }
0316 }
0317 else if (frac_digits)
0318 {
0319
0320 bool r = traits::scale(-frac_digits, n, acc_n);
0321 BOOST_VERIFY(r);
0322 }
0323 else
0324 {
0325 if (excess_n)
0326 {
0327 if (!traits::scale(excess_n, n, acc_n))
0328 return false;
0329 }
0330 else
0331 {
0332 n = static_cast<T>(acc_n);
0333 }
0334 }
0335
0336
0337 traits::assign_to(traits::negate(neg, n), attr);
0338
0339
0340 return true;
0341 }
0342 };
0343
0344 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0345 # pragma warning(pop)
0346 #endif
0347
0348 }}}}
0349
0350 #endif