|
||||
File indexing completed on 2025-01-19 09:47:38
0001 // Copyright (c) 2001-2011 Hartmut Kaiser 0002 // 0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0005 0006 #if !defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM) 0007 #define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM 0008 0009 #if defined(_MSC_VER) 0010 #pragma once 0011 #endif 0012 0013 #include <boost/config/no_tr1/cmath.hpp> 0014 #include <boost/type_traits/remove_const.hpp> 0015 0016 #include <boost/spirit/home/support/char_class.hpp> 0017 #include <boost/spirit/home/karma/generator.hpp> 0018 #include <boost/spirit/home/karma/char.hpp> 0019 #include <boost/spirit/home/karma/numeric/int.hpp> 0020 #include <boost/spirit/home/karma/numeric/detail/real_utils.hpp> 0021 0022 #include <boost/mpl/bool.hpp> 0023 0024 namespace boost { namespace spirit { namespace karma 0025 { 0026 /////////////////////////////////////////////////////////////////////////// 0027 // 0028 // real_policies, if you need special handling of your floating 0029 // point numbers, just overload this policy class and use it as a template 0030 // parameter to the karma::real_generator floating point specifier: 0031 // 0032 // template <typename T> 0033 // struct scientific_policy : karma::real_policies<T> 0034 // { 0035 // // we want the numbers always to be in scientific format 0036 // static int floatfield(T n) { return fmtflags::scientific; } 0037 // }; 0038 // 0039 // typedef 0040 // karma::real_generator<double, scientific_policy<double> > 0041 // science_type; 0042 // 0043 // karma::generate(sink, science_type(), 1.0); // will output: 1.0e00 0044 // 0045 /////////////////////////////////////////////////////////////////////////// 0046 template <typename T> 0047 struct real_policies 0048 { 0049 /////////////////////////////////////////////////////////////////////// 0050 // Expose the data type the generator is targeted at 0051 /////////////////////////////////////////////////////////////////////// 0052 typedef T value_type; 0053 0054 /////////////////////////////////////////////////////////////////////// 0055 // By default the policy doesn't require any special iterator 0056 // functionality. The floating point generator exposes its properties 0057 // from here, so this needs to be updated in case other properties 0058 // need to be implemented. 0059 /////////////////////////////////////////////////////////////////////// 0060 typedef mpl::int_<generator_properties::no_properties> properties; 0061 0062 /////////////////////////////////////////////////////////////////////// 0063 // Specifies, which representation type to use during output 0064 // generation. 0065 /////////////////////////////////////////////////////////////////////// 0066 struct fmtflags 0067 { 0068 enum { 0069 scientific = 0, // Generate floating-point values in scientific 0070 // format (with an exponent field). 0071 fixed = 1 // Generate floating-point values in fixed-point 0072 // format (with no exponent field). 0073 }; 0074 }; 0075 0076 /////////////////////////////////////////////////////////////////////// 0077 // This is the main function used to generate the output for a 0078 // floating point number. It is called by the real generator in order 0079 // to perform the conversion. In theory all of the work can be 0080 // implemented here, but it is the easiest to use existing 0081 // functionality provided by the type specified by the template 0082 // parameter `Inserter`. 0083 // 0084 // sink: the output iterator to use for generation 0085 // n: the floating point number to convert 0086 // p: the instance of the policy type used to instantiate this 0087 // floating point generator. 0088 /////////////////////////////////////////////////////////////////////// 0089 template <typename Inserter, typename OutputIterator, typename Policies> 0090 static bool 0091 call (OutputIterator& sink, T n, Policies const& p) 0092 { 0093 return Inserter::call_n(sink, n, p); 0094 } 0095 0096 /////////////////////////////////////////////////////////////////////// 0097 // The default behavior is to not to require generating a sign. If 0098 // 'force_sign()' returns true, then all generated numbers will 0099 // have a sign ('+' or '-', zeros will have a space instead of a sign) 0100 // 0101 // n The floating point number to output. This can be used to 0102 // adjust the required behavior depending on the value of 0103 // this number. 0104 /////////////////////////////////////////////////////////////////////// 0105 static bool force_sign(T) 0106 { 0107 return false; 0108 } 0109 0110 /////////////////////////////////////////////////////////////////////// 0111 // Return whether trailing zero digits have to be emitted in the 0112 // fractional part of the output. If set, this flag instructs the 0113 // floating point generator to emit trailing zeros up to the required 0114 // precision digits (as returned by the precision() function). 0115 // 0116 // n The floating point number to output. This can be used to 0117 // adjust the required behavior depending on the value of 0118 // this number. 0119 /////////////////////////////////////////////////////////////////////// 0120 static bool trailing_zeros(T) 0121 { 0122 // the default behavior is not to generate trailing zeros 0123 return false; 0124 } 0125 0126 /////////////////////////////////////////////////////////////////////// 0127 // Decide, which representation type to use in the generated output. 0128 // 0129 // By default all numbers having an absolute value of zero or in 0130 // between 0.001 and 100000 will be generated using the fixed format, 0131 // all others will be generated using the scientific representation. 0132 // 0133 // The function trailing_zeros() can be used to force the output of 0134 // trailing zeros in the fractional part up to the number of digits 0135 // returned by the precision() member function. The default is not to 0136 // generate the trailing zeros. 0137 // 0138 // n The floating point number to output. This can be used to 0139 // adjust the formatting flags depending on the value of 0140 // this number. 0141 /////////////////////////////////////////////////////////////////////// 0142 static int floatfield(T n) 0143 { 0144 if (traits::test_zero(n)) 0145 return fmtflags::fixed; 0146 0147 T abs_n = traits::get_absolute_value(n); 0148 return (abs_n >= 1e5 || abs_n < 1e-3) 0149 ? fmtflags::scientific : fmtflags::fixed; 0150 } 0151 0152 /////////////////////////////////////////////////////////////////////// 0153 // Return the maximum number of decimal digits to generate in the 0154 // fractional part of the output. 0155 // 0156 // n The floating point number to output. This can be used to 0157 // adjust the required precision depending on the value of 0158 // this number. If the trailing zeros flag is specified the 0159 // fractional part of the output will be 'filled' with 0160 // zeros, if appropriate 0161 // 0162 // Note: If the trailing_zeros flag is not in effect additional 0163 // comments apply. See the comment for the fraction_part() 0164 // function below. 0165 /////////////////////////////////////////////////////////////////////// 0166 static unsigned precision(T) 0167 { 0168 // by default, generate max. 3 fractional digits 0169 return 3; 0170 } 0171 0172 /////////////////////////////////////////////////////////////////////// 0173 // Generate the integer part of the number. 0174 // 0175 // sink The output iterator to use for generation 0176 // n The absolute value of the integer part of the floating 0177 // point number to convert (always non-negative). 0178 // sign The sign of the overall floating point number to 0179 // convert. 0180 // force_sign Whether a sign has to be generated even for 0181 // non-negative numbers. Note, that force_sign will be 0182 // set to false for zero floating point values. 0183 /////////////////////////////////////////////////////////////////////// 0184 template <typename OutputIterator> 0185 static bool integer_part (OutputIterator& sink, T n, bool sign 0186 , bool force_sign) 0187 { 0188 return sign_inserter::call( 0189 sink, traits::test_zero(n), sign, force_sign, force_sign) && 0190 int_inserter<10>::call(sink, n); 0191 } 0192 0193 /////////////////////////////////////////////////////////////////////// 0194 // Generate the decimal point. 0195 // 0196 // sink The output iterator to use for generation 0197 // n The fractional part of the floating point number to 0198 // convert. Note that this number is scaled such, that 0199 // it represents the number of units which correspond 0200 // to the value returned from the precision() function 0201 // earlier. I.e. a fractional part of 0.01234 is 0202 // represented as 1234 when the 'Precision' is 5. 0203 // precision The number of digits to emit as returned by the 0204 // function 'precision()' above 0205 // 0206 // This is given to allow to decide, whether a decimal point 0207 // has to be generated at all. 0208 // 0209 // Note: If the trailing_zeros flag is not in effect additional 0210 // comments apply. See the comment for the fraction_part() 0211 // function below. 0212 /////////////////////////////////////////////////////////////////////// 0213 template <typename OutputIterator> 0214 static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/) 0215 { 0216 return char_inserter<>::call(sink, '.'); // generate the dot by default 0217 } 0218 0219 /////////////////////////////////////////////////////////////////////// 0220 // Generate the fractional part of the number. 0221 // 0222 // sink The output iterator to use for generation 0223 // n The fractional part of the floating point number to 0224 // convert. This number is scaled such, that it represents 0225 // the number of units which correspond to the 'Precision'. 0226 // I.e. a fractional part of 0.01234 is represented as 1234 0227 // when the 'precision_' parameter is 5. 0228 // precision_ The corrected number of digits to emit (see note 0229 // below) 0230 // precision The number of digits to emit as returned by the 0231 // function 'precision()' above 0232 // 0233 // Note: If trailing_zeros() does not return true the 'precision_' 0234 // parameter will have been corrected from the value the 0235 // precision() function returned earlier (defining the maximal 0236 // number of fractional digits) in the sense, that it takes into 0237 // account trailing zeros. I.e. a floating point number 0.0123 0238 // and a value of 5 returned from precision() will result in: 0239 // 0240 // trailing_zeros is not specified: 0241 // n 123 0242 // precision_ 4 0243 // 0244 // trailing_zeros is specified: 0245 // n 1230 0246 // precision_ 5 0247 // 0248 /////////////////////////////////////////////////////////////////////// 0249 template <typename OutputIterator> 0250 static bool fraction_part (OutputIterator& sink, T n 0251 , unsigned precision_, unsigned precision) 0252 { 0253 // allow for ADL to find the correct overload for floor and log10 0254 using namespace std; 0255 0256 // The following is equivalent to: 0257 // generate(sink, right_align(precision, '0')[ulong], n); 0258 // but it's spelled out to avoid inter-modular dependencies. 0259 0260 typename remove_const<T>::type digits = 0261 (traits::test_zero(n) ? 1 : ceil(log10(n + T(1.)))); 0262 bool r = true; 0263 for (/**/; r && digits < precision_; digits = digits + 1) 0264 r = char_inserter<>::call(sink, '0'); 0265 if (precision && r) 0266 r = int_inserter<10>::call(sink, n); 0267 return r; 0268 } 0269 0270 /////////////////////////////////////////////////////////////////////// 0271 // Generate the exponential part of the number (this is called only 0272 // if the floatfield() function returned the 'scientific' flag). 0273 // 0274 // sink The output iterator to use for generation 0275 // n The (signed) exponential part of the floating point 0276 // number to convert. 0277 // 0278 // The Tag template parameter is either of the type unused_type or 0279 // describes the character class and conversion to be applied to any 0280 // output possibly influenced by either the lower[...] or upper[...] 0281 // directives. 0282 /////////////////////////////////////////////////////////////////////// 0283 template <typename CharEncoding, typename Tag, typename OutputIterator> 0284 static bool exponent (OutputIterator& sink, long n) 0285 { 0286 long abs_n = traits::get_absolute_value(n); 0287 bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') && 0288 sign_inserter::call(sink, traits::test_zero(n) 0289 , traits::test_negative(n), false); 0290 0291 // the C99 Standard requires at least two digits in the exponent 0292 if (r && abs_n < 10) 0293 r = char_inserter<CharEncoding, Tag>::call(sink, '0'); 0294 return r && int_inserter<10>::call(sink, abs_n); 0295 } 0296 0297 /////////////////////////////////////////////////////////////////////// 0298 // Print the textual representations for non-normal floats (NaN and 0299 // Inf) 0300 // 0301 // sink The output iterator to use for generation 0302 // n The (signed) floating point number to convert. 0303 // force_sign Whether a sign has to be generated even for 0304 // non-negative numbers 0305 // 0306 // The Tag template parameter is either of the type unused_type or 0307 // describes the character class and conversion to be applied to any 0308 // output possibly influenced by either the lower[...] or upper[...] 0309 // directives. 0310 // 0311 // Note: These functions get called only if fpclassify() returned 0312 // FP_INFINITY or FP_NAN. 0313 /////////////////////////////////////////////////////////////////////// 0314 template <typename CharEncoding, typename Tag, typename OutputIterator> 0315 static bool nan (OutputIterator& sink, T n, bool force_sign) 0316 { 0317 return sign_inserter::call( 0318 sink, false, traits::test_negative(n), force_sign) && 0319 string_inserter<CharEncoding, Tag>::call(sink, "nan"); 0320 } 0321 0322 template <typename CharEncoding, typename Tag, typename OutputIterator> 0323 static bool inf (OutputIterator& sink, T n, bool force_sign) 0324 { 0325 return sign_inserter::call( 0326 sink, false, traits::test_negative(n), force_sign) && 0327 string_inserter<CharEncoding, Tag>::call(sink, "inf"); 0328 } 0329 }; 0330 }}} 0331 0332 #endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |