blob: ff375f28d5a2524d32c87b8110fb13b9e9e41421 [file] [log] [blame]
// Copyright (c) 2001-2009 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) && (_MSC_VER >= 1020)
#pragma once // MS compatible compilers support #pragma once
#endif
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/int.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/spirit/home/support/detail/math/fpclassify.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// real_generator_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_spec floating point specifier:
//
// template <typename T>
// struct scientific_policy : karma::real_generator_policies<T>
// {
// // we want the numbers always to be in scientific format
// static int floatfield(T n) { return scientific; }
// };
//
// typedef
// karma::real_spec<double, scientific_policy<double> >
// science_type;
//
// karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_generator_policies
{
///////////////////////////////////////////////////////////////////////
// Specifies, which representation type to use during output
// generation.
///////////////////////////////////////////////////////////////////////
enum fmtflags
{
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).
};
///////////////////////////////////////////////////////////////////////
// The default behavior is to not to require generating a sign. If
// 'force_sign' is specified as true, then all generated numbers will
// have a sign ('+' or '-', zeros will have a space instead of a sign)
///////////////////////////////////////////////////////////////////////
static bool const force_sign = false;
///////////////////////////////////////////////////////////////////////
// The 'trailing_zeros' flag instructs the floating point generator to
// emit trailing zeros up to the required precision digits.
///////////////////////////////////////////////////////////////////////
static bool const trailing_zeros = 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 trailing_zeros flag 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 (detail::is_zero(n))
return fixed;
T abs_n = detail::absolute_value(n);
return (abs_n >= 1e5 || abs_n < 1e-3) ? scientific : fixed;
}
///////////////////////////////////////////////////////////////////////
// The 'fractional_precision' constant specifies the default number of
// digits to generate for the fractional part of a floating point
// number. This is used by this (default) policies implementation
// only. If you need another fractional precision you'll have to
// overload the precision function below.
//
// Note: The actual number of digits for a floating point number is
// determined by the precision() function below. This allows to
// have different precisions depending on the value of the
// floating point number.
///////////////////////////////////////////////////////////////////////
static unsigned int const fractional_precision = 3;
///////////////////////////////////////////////////////////////////////
// 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<T>::digits10 + 1
///////////////////////////////////////////////////////////////////////
static unsigned int
precision(T)
{
// generate max. 'fractional_precision' fractional digits
return fractional_precision;
}
///////////////////////////////////////////////////////////////////////
// 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.
///////////////////////////////////////////////////////////////////////
template <bool ForceSign, typename OutputIterator>
static bool
integer_part (OutputIterator& sink, T n, bool sign)
{
return sign_inserter<ForceSign>::call(
sink, detail::is_zero(n), 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.
//
// 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)
{
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.
//
// Note: If the trailing_zeros flag is not returned from the
// floatfield() function, 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_)
{
// 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.
T digits = (detail::is_zero(n) ? 0 : floor(log10(n))) + 1;
bool r = true;
for (/**/; r && digits < precision_; digits = digits + 1)
r = char_inserter<>::call(sink, '0');
return r && int_inserter<10>::call(sink, n);
}
///////////////////////////////////////////////////////////////////////
// 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 Tag, typename OutputIterator>
static bool
exponent (OutputIterator& sink, T n)
{
T abs_n = detail::absolute_value(n);
bool r = char_inserter<Tag>::call(sink, 'e') &&
sign_inserter<false>::call(
sink, detail::is_zero(n), detail::is_negative(n));
// the C99 Standard requires at least two digits in the exponent
if (r && abs_n < 10)
r = char_inserter<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.
//
// 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 <bool ForceSign, typename Tag, typename OutputIterator>
static bool
nan (OutputIterator& sink, T n)
{
return sign_inserter<ForceSign>::call(
sink, false, detail::is_negative(n)) &&
string_inserter<Tag>::call(sink, "nan");
}
template <bool ForceSign, typename Tag, typename OutputIterator>
static bool
inf (OutputIterator& sink, T n)
{
return sign_inserter<ForceSign>::call(
sink, false, detail::is_negative(n)) &&
string_inserter<Tag>::call(sink, "inf");
}
};
}}}
#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)