File indexing completed on 2025-01-19 09:47:37
0001
0002
0003
0004
0005
0006 #if !defined(BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM)
0007 #define BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM
0008
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012
0013 #include <boost/config.hpp>
0014 #include <boost/config/no_tr1/cmath.hpp>
0015 #include <boost/detail/workaround.hpp>
0016 #include <boost/limits.hpp>
0017
0018 #include <boost/spirit/home/support/char_class.hpp>
0019 #include <boost/spirit/home/support/unused.hpp>
0020 #include <boost/spirit/home/support/detail/pow10.hpp>
0021 #include <boost/spirit/home/karma/detail/generate_to.hpp>
0022 #include <boost/spirit/home/karma/detail/string_generate.hpp>
0023 #include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
0024
0025 namespace boost { namespace spirit { namespace karma
0026 {
0027
0028
0029
0030
0031
0032
0033
0034 template <typename T>
0035 struct real_policies;
0036
0037 template <typename T
0038 , typename Policies = real_policies<T>
0039 , typename CharEncoding = unused_type
0040 , typename Tag = unused_type>
0041 struct real_inserter
0042 {
0043 template <typename OutputIterator, typename U>
0044 static bool
0045 call (OutputIterator& sink, U n, Policies const& p = Policies())
0046 {
0047 if (traits::test_nan(n)) {
0048 return p.template nan<CharEncoding, Tag>(
0049 sink, n, p.force_sign(n));
0050 }
0051 else if (traits::test_infinite(n)) {
0052 return p.template inf<CharEncoding, Tag>(
0053 sink, n, p.force_sign(n));
0054 }
0055 return p.template call<real_inserter>(sink, n, p);
0056 }
0057
0058 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0059 # pragma warning(push)
0060 # pragma warning(disable: 4100)
0061 # pragma warning(disable: 4127)
0062 # pragma warning(disable: 4267)
0063 #endif
0064
0065
0066
0067 template <typename OutputIterator, typename U>
0068 static bool
0069 call_n (OutputIterator& sink, U n, Policies const& p)
0070 {
0071
0072 bool force_sign = p.force_sign(n);
0073 bool sign_val = false;
0074 int flags = p.floatfield(n);
0075 if (traits::test_negative(n))
0076 {
0077 n = -n;
0078 sign_val = true;
0079 }
0080
0081
0082
0083
0084
0085 unsigned precision = p.precision(n);
0086
0087
0088 using namespace std;
0089
0090 bool precexp_offset = false;
0091 U dim = 0;
0092 if (0 == (Policies::fmtflags::fixed & flags) && !traits::test_zero(n))
0093 {
0094 dim = log10(n);
0095 if (dim > 0)
0096 n /= spirit::traits::pow10<U>(traits::truncate_to_long::call(dim));
0097 else if (n < 1.) {
0098 long exp = traits::truncate_to_long::call(-dim);
0099
0100 dim = static_cast<U>(-exp);
0101
0102
0103 if (exp > std::numeric_limits<U>::max_exponent10)
0104 {
0105 n *= spirit::traits::pow10<U>(std::numeric_limits<U>::max_exponent10);
0106 n *= spirit::traits::pow10<U>(exp - std::numeric_limits<U>::max_exponent10);
0107 }
0108 else
0109 n *= spirit::traits::pow10<U>(exp);
0110
0111 if (n < 1.)
0112 {
0113 n *= 10.;
0114 --dim;
0115 precexp_offset = true;
0116 }
0117 }
0118 }
0119
0120
0121 U integer_part;
0122 U precexp = spirit::traits::pow10<U>(precision);
0123 U fractional_part = modf(n, &integer_part);
0124
0125 if (precexp_offset)
0126 {
0127 fractional_part =
0128 floor((fractional_part * precexp + U(0.5)) * U(10.)) / U(10.);
0129 }
0130 else
0131 {
0132 fractional_part = floor(fractional_part * precexp + U(0.5));
0133 }
0134
0135 if (fractional_part >= precexp)
0136 {
0137 fractional_part = floor(fractional_part - precexp);
0138 integer_part += 1;
0139 if (integer_part >= 10. && 0 == (Policies::fmtflags::fixed & flags))
0140 {
0141 integer_part /= 10.;
0142 ++dim;
0143 }
0144 }
0145
0146
0147
0148 U long_int_part = floor(integer_part);
0149 U long_frac_part = fractional_part;
0150 unsigned prec = precision;
0151 if (!p.trailing_zeros(n))
0152 {
0153 U frac_part_floor = long_frac_part;
0154 if (0 != long_frac_part) {
0155
0156 while (0 != prec &&
0157 0 == traits::remainder<10>::call(long_frac_part))
0158 {
0159 long_frac_part = traits::divide<10>::call(long_frac_part);
0160 --prec;
0161 }
0162 }
0163 else {
0164
0165
0166 prec = 0;
0167 }
0168
0169 if (precision != prec)
0170 {
0171 long_frac_part = frac_part_floor /
0172 spirit::traits::pow10<U>(precision-prec);
0173 }
0174 }
0175
0176
0177 if ((force_sign || sign_val) &&
0178 traits::test_zero(long_int_part) &&
0179 traits::test_zero(long_frac_part))
0180 {
0181 sign_val = false;
0182 force_sign = false;
0183 }
0184
0185
0186 bool r = p.integer_part(sink, long_int_part, sign_val, force_sign);
0187
0188
0189 r = r && p.dot(sink, long_frac_part, precision);
0190
0191
0192 r = r && p.fraction_part(sink, long_frac_part, prec, precision);
0193
0194 if (r && 0 == (Policies::fmtflags::fixed & flags)) {
0195 return p.template exponent<CharEncoding, Tag>(sink,
0196 traits::truncate_to_long::call(dim));
0197 }
0198 return r;
0199 }
0200
0201 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0202 # pragma warning(pop)
0203 #endif
0204
0205 };
0206 }}}
0207
0208 #endif
0209