123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- // 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 <boost/config/no_tr1/cmath.hpp>
- #include <boost/type_traits/remove_const.hpp>
- #include <boost/spirit/home/support/char_class.hpp>
- #include <boost/spirit/home/karma/generator.hpp>
- #include <boost/spirit/home/karma/char.hpp>
- #include <boost/spirit/home/karma/numeric/int.hpp>
- #include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
- #include <boost/mpl/bool.hpp>
- 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 <typename T>
- // struct scientific_policy : karma::real_policies<T>
- // {
- // // we want the numbers always to be in scientific format
- // static int floatfield(T n) { return fmtflags::scientific; }
- // };
- //
- // typedef
- // karma::real_generator<double, scientific_policy<double> >
- // science_type;
- //
- // karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
- //
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- 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_<generator_properties::no_properties> 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 <typename Inserter, typename OutputIterator, typename Policies>
- 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.
- ///////////////////////////////////////////////////////////////////////
- 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 <typename OutputIterator>
- 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 <typename OutputIterator>
- 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 <typename OutputIterator>
- 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<T>::type digits =
- (traits::test_zero(n) ? 1 : ceil(log10(n + T(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 <typename CharEncoding, typename Tag, typename OutputIterator>
- static bool exponent (OutputIterator& sink, long n)
- {
- long abs_n = traits::get_absolute_value(n);
- bool r = char_inserter<CharEncoding, Tag>::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<CharEncoding, Tag>::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 <typename CharEncoding, typename Tag, typename OutputIterator>
- static bool nan (OutputIterator& sink, T n, bool force_sign)
- {
- return sign_inserter::call(
- sink, false, traits::test_negative(n), force_sign) &&
- string_inserter<CharEncoding, Tag>::call(sink, "nan");
- }
- template <typename CharEncoding, typename Tag, typename OutputIterator>
- static bool inf (OutputIterator& sink, T n, bool force_sign)
- {
- return sign_inserter::call(
- sink, false, traits::test_negative(n), force_sign) &&
- string_inserter<CharEncoding, Tag>::call(sink, "inf");
- }
- };
- }}}
- #endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
|