text: //  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/math/special_functions/fpclassify.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. Moreover, this precision will be limited
          //            to the value of std::numeric_limits<T>::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 <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) ? 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 <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)
  