// Copyright (c) 2001-2011 Hartmut Kaiser // // 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_KARMA_REAL_POLICIES_MAR_02_2007_0936AM) #define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { namespace karma { /////////////////////////////////////////////////////////////////////////// // // real_policies, if you need special handling of your floating // point numbers, just overload this policy class and use it as a template // parameter to the karma::real_generator floating point specifier: // // template // struct scientific_policy : karma::real_policies // { // // we want the numbers always to be in scientific format // static int floatfield(T n) { return fmtflags::scientific; } // }; // // typedef // karma::real_generator > // science_type; // // karma::generate(sink, science_type(), 1.0); // will output: 1.0e00 // /////////////////////////////////////////////////////////////////////////// template struct real_policies { /////////////////////////////////////////////////////////////////////// // Expose the data type the generator is targeted at /////////////////////////////////////////////////////////////////////// typedef T value_type; /////////////////////////////////////////////////////////////////////// // By default the policy doesn't require any special iterator // functionality. The floating point generator exposes its properties // from here, so this needs to be updated in case other properties // need to be implemented. /////////////////////////////////////////////////////////////////////// typedef mpl::int_ properties; /////////////////////////////////////////////////////////////////////// // Specifies, which representation type to use during output // generation. /////////////////////////////////////////////////////////////////////// struct fmtflags { enum { scientific = 0, // Generate floating-point values in scientific // format (with an exponent field). fixed = 1 // Generate floating-point values in fixed-point // format (with no exponent field). }; }; /////////////////////////////////////////////////////////////////////// // This is the main function used to generate the output for a // floating point number. It is called by the real generator in order // to perform the conversion. In theory all of the work can be // implemented here, but it is the easiest to use existing // functionality provided by the type specified by the template // parameter `Inserter`. // // sink: the output iterator to use for generation // n: the floating point number to convert // p: the instance of the policy type used to instantiate this // floating point generator. /////////////////////////////////////////////////////////////////////// template static bool call (OutputIterator& sink, T n, Policies const& p) { return Inserter::call_n(sink, n, p); } /////////////////////////////////////////////////////////////////////// // The default behavior is to not to require generating a sign. If // 'force_sign()' returns true, then all generated numbers will // have a sign ('+' or '-', zeros will have a space instead of a sign) // // n The floating point number to output. This can be used to // adjust the required behavior depending on the value of // this number. /////////////////////////////////////////////////////////////////////// static bool force_sign(T) { return false; } /////////////////////////////////////////////////////////////////////// // Return whether trailing zero digits have to be emitted in the // fractional part of the output. If set, this flag instructs the // floating point generator to emit trailing zeros up to the required // precision digits (as returned by the precision() function). // // n The floating point number to output. This can be used to // adjust the required behavior depending on the value of // this number. /////////////////////////////////////////////////////////////////////// static bool trailing_zeros(T) { // the default behavior is not to generate trailing zeros return false; } /////////////////////////////////////////////////////////////////////// // Decide, which representation type to use in the generated output. // // By default all numbers having an absolute value of zero or in // between 0.001 and 100000 will be generated using the fixed format, // all others will be generated using the scientific representation. // // The function trailing_zeros() can be used to force the output of // trailing zeros in the fractional part up to the number of digits // returned by the precision() member function. The default is not to // generate the trailing zeros. // // n The floating point number to output. This can be used to // adjust the formatting flags depending on the value of // this number. /////////////////////////////////////////////////////////////////////// static int floatfield(T n) { if (traits::test_zero(n)) return fmtflags::fixed; T abs_n = traits::get_absolute_value(n); return (abs_n >= 1e5 || abs_n < 1e-3) ? fmtflags::scientific : fmtflags::fixed; } /////////////////////////////////////////////////////////////////////// // Return the maximum number of decimal digits to generate in the // fractional part of the output. // // n The floating point number to output. This can be used to // adjust the required precision depending on the value of // this number. If the trailing zeros flag is specified the // fractional part of the output will be 'filled' with // zeros, if appropriate // // Note: If the trailing_zeros flag is not in effect additional // comments apply. See the comment for the fraction_part() // function below. Moreover, this precision will be limited // to the value of std::numeric_limits::digits10 + 1 /////////////////////////////////////////////////////////////////////// static unsigned precision(T) { // by default, generate max. 3 fractional digits return 3; } /////////////////////////////////////////////////////////////////////// // Generate the integer part of the number. // // sink The output iterator to use for generation // n The absolute value of the integer part of the floating // point number to convert (always non-negative). // sign The sign of the overall floating point number to // convert. // force_sign Whether a sign has to be generated even for // non-negative numbers. Note, that force_sign will be // set to false for zero floating point values. /////////////////////////////////////////////////////////////////////// template static bool integer_part (OutputIterator& sink, T n, bool sign , bool force_sign) { return sign_inserter::call( sink, traits::test_zero(n), sign, force_sign, force_sign) && int_inserter<10>::call(sink, n); } /////////////////////////////////////////////////////////////////////// // Generate the decimal point. // // sink The output iterator to use for generation // n The fractional part of the floating point number to // convert. Note that this number is scaled such, that // it represents the number of units which correspond // to the value returned from the precision() function // earlier. I.e. a fractional part of 0.01234 is // represented as 1234 when the 'Precision' is 5. // precision The number of digits to emit as returned by the // function 'precision()' above // // This is given to allow to decide, whether a decimal point // has to be generated at all. // // Note: If the trailing_zeros flag is not in effect additional // comments apply. See the comment for the fraction_part() // function below. /////////////////////////////////////////////////////////////////////// template static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/) { return char_inserter<>::call(sink, '.'); // generate the dot by default } /////////////////////////////////////////////////////////////////////// // Generate the fractional part of the number. // // sink The output iterator to use for generation // n The fractional part of the floating point number to // convert. This number is scaled such, that it represents // the number of units which correspond to the 'Precision'. // I.e. a fractional part of 0.01234 is represented as 1234 // when the 'precision_' parameter is 5. // precision_ The corrected number of digits to emit (see note // below) // precision The number of digits to emit as returned by the // function 'precision()' above // // Note: If trailing_zeros() does not return true the 'precision_' // parameter will have been corrected from the value the // precision() function returned earlier (defining the maximal // number of fractional digits) in the sense, that it takes into // account trailing zeros. I.e. a floating point number 0.0123 // and a value of 5 returned from precision() will result in: // // trailing_zeros is not specified: // n 123 // precision_ 4 // // trailing_zeros is specified: // n 1230 // precision_ 5 // /////////////////////////////////////////////////////////////////////// template static bool fraction_part (OutputIterator& sink, T n , unsigned precision_, unsigned precision) { // allow for ADL to find the correct overload for floor and log10 using namespace std; // The following is equivalent to: // generate(sink, right_align(precision, '0')[ulong], n); // but it's spelled out to avoid inter-modular dependencies. typename remove_const::type digits = (traits::test_zero(n) ? 0 : floor(log10(n))) + 1; bool r = true; for (/**/; r && digits < precision_; digits = digits + 1) r = char_inserter<>::call(sink, '0'); if (precision && r) r = int_inserter<10>::call(sink, n); return r; } /////////////////////////////////////////////////////////////////////// // Generate the exponential part of the number (this is called only // if the floatfield() function returned the 'scientific' flag). // // sink The output iterator to use for generation // n The (signed) exponential part of the floating point // number to convert. // // The Tag template parameter is either of the type unused_type or // describes the character class and conversion to be applied to any // output possibly influenced by either the lower[...] or upper[...] // directives. /////////////////////////////////////////////////////////////////////// template static bool exponent (OutputIterator& sink, long n) { long abs_n = traits::get_absolute_value(n); bool r = char_inserter::call(sink, 'e') && sign_inserter::call(sink, traits::test_zero(n) , traits::test_negative(n), false); // the C99 Standard requires at least two digits in the exponent if (r && abs_n < 10) r = char_inserter::call(sink, '0'); return r && int_inserter<10>::call(sink, abs_n); } /////////////////////////////////////////////////////////////////////// // Print the textual representations for non-normal floats (NaN and // Inf) // // sink The output iterator to use for generation // n The (signed) floating point number to convert. // force_sign Whether a sign has to be generated even for // non-negative numbers // // The Tag template parameter is either of the type unused_type or // describes the character class and conversion to be applied to any // output possibly influenced by either the lower[...] or upper[...] // directives. // // Note: These functions get called only if fpclassify() returned // FP_INFINITY or FP_NAN. /////////////////////////////////////////////////////////////////////// template static bool nan (OutputIterator& sink, T n, bool force_sign) { return sign_inserter::call( sink, false, traits::test_negative(n), force_sign) && string_inserter::call(sink, "nan"); } template static bool inf (OutputIterator& sink, T n, bool force_sign) { return sign_inserter::call( sink, false, traits::test_negative(n), force_sign) && string_inserter::call(sink, "inf"); } }; }}} #endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)