$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55585 - in trunk/boost/spirit/home/karma: detail directive numeric numeric/detail
From: hartmut.kaiser_at_[hidden]
Date: 2009-08-14 16:25:03
Author: hkaiser
Date: 2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
New Revision: 55585
URL: http://svn.boost.org/trac/boost/changeset/55585
Log:
Spirit: adjustments to real_policies to accommodate more use cases
Text files modified: 
   trunk/boost/spirit/home/karma/detail/output_iterator.hpp       |     5 +                                       
   trunk/boost/spirit/home/karma/directive/right_alignment.hpp    |     2                                         
   trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp |    75 +++++++++++++++++-----------            
   trunk/boost/spirit/home/karma/numeric/int.hpp                  |    12 ++--                                    
   trunk/boost/spirit/home/karma/numeric/real.hpp                 |     4 +                                       
   trunk/boost/spirit/home/karma/numeric/real_policies.hpp        |   105 ++++++++++++++++++++++++++++----------- 
   6 files changed, 135 insertions(+), 68 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/output_iterator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/output_iterator.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/output_iterator.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -248,7 +248,7 @@
         void enable(std::size_t width_) 
         { 
             tidy();             // release existing buffer
-            width = width_; 
+            width = (width_ == std::size_t(-1)) ? 0 : width_;
         }
 
         void tidy() 
@@ -529,7 +529,8 @@
     template <typename OutputIterator>
     struct enable_buffering
     {
-        enable_buffering(OutputIterator& sink_, std::size_t width = 0)
+        enable_buffering(OutputIterator& sink_
+              , std::size_t width = std::size_t(-1))
           : sink(sink_), prev_buffer(NULL), enabled(false)
         {
             buffer_data.enable(width);
Modified: trunk/boost/spirit/home/karma/directive/right_alignment.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/right_alignment.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/right_alignment.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -98,7 +98,7 @@
             }   // re-enable counting
 
             buffering.disable();    // do not perform buffering any more
-            
+
             // generate the left padding
             detail::enable_counting<OutputIterator> counting(sink, buffering.buffer_size());
             while(r && counting.count() < width) 
Modified: trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -547,16 +547,15 @@
     //
     //  The sign_inserter template generates a sign for a given numeric value.
     //
-    //    The parameter ForceSign allows to generate a sign even for positive  
+    //    The parameter forcesign allows to generate a sign even for positive  
     //    numbers.
     //
     ///////////////////////////////////////////////////////////////////////////
-    template <bool ForceSign>
     struct sign_inserter
     {
         template <typename OutputIterator>
         static bool
-        call(OutputIterator& sink, bool /*is_zero*/, bool is_negative)
+        call_noforce(OutputIterator& sink, bool /*is_zero*/, bool is_negative)
         {
             // generate a sign for negative numbers only
             if (is_negative) {
@@ -565,14 +564,10 @@
             }
             return true;
         }
-    };
 
-    template <>
-    struct sign_inserter<true>
-    {
         template <typename OutputIterator>
         static bool
-        call(OutputIterator& sink, bool is_zero, bool is_negative)
+        call_force(OutputIterator& sink, bool is_zero, bool is_negative)
         {
             // generate a sign for all numbers except zero
             if (!is_zero) 
@@ -583,6 +578,16 @@
             ++sink;
             return true;
         }
+
+        template <typename OutputIterator>
+        static bool
+        call(OutputIterator& sink, bool is_zero, bool is_negative
+          , bool forcesign)
+        {
+            return forcesign ?
+                call_force(sink, is_zero, is_negative) :
+                call_noforce(sink, is_zero, is_negative);
+        }
     };
 
     ///////////////////////////////////////////////////////////////////////////
@@ -625,18 +630,20 @@
       , typename Tag = unused_type>
     struct real_inserter
     {
-        enum { force_sign = Policies::force_sign };
-
         template <typename OutputIterator>
         static bool
         call (OutputIterator& sink, float n, Policies const& p = Policies())
         {
             int fpclass = (math::fpclassify)(n);
-            if ((int)FP_NAN == fpclass)
-                return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
-            else if ((int)FP_INFINITE == fpclass)
-                return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
-            return call_n(sink, n, p);
+            if ((int)FP_NAN == fpclass) {
+                return Policies::template nan<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            else if ((int)FP_INFINITE == fpclass) {
+                return Policies::template inf<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            return p.template call<real_inserter>(sink, n, p);
         }
 
         template <typename OutputIterator>
@@ -644,11 +651,15 @@
         call (OutputIterator& sink, double n, Policies const& p = Policies())
         {
             int fpclass = (math::fpclassify)(n);
-            if ((int)FP_NAN == fpclass)
-                return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
-            else if ((int)FP_INFINITE == fpclass)
-                return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
-            return call_n(sink, n, p);
+            if ((int)FP_NAN == fpclass) {
+                return Policies::template nan<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            else if ((int)FP_INFINITE == fpclass) {
+                return Policies::template inf<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            return p.template call<real_inserter>(sink, n, p);
         }
 
         template <typename OutputIterator>
@@ -656,11 +667,15 @@
         call (OutputIterator& sink, long double n, Policies const& p = Policies())
         {
             int fpclass = (math::fpclassify)(n);
-            if ((int)FP_NAN == fpclass)
-                return Policies::template nan<force_sign, CharEncoding, Tag>(sink, n);
-            else if ((int)FP_INFINITE == fpclass)
-                return Policies::template inf<force_sign, CharEncoding, Tag>(sink, n);
-            return call_n(sink, n, p);
+            if ((int)FP_NAN == fpclass) {
+                return Policies::template nan<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            else if ((int)FP_INFINITE == fpclass) {
+                return Policies::template inf<CharEncoding, Tag>(
+                    sink, n, p.force_sign(n));
+            }
+            return p.template call<real_inserter>(sink, n, p);
         }
 
         template <typename OutputIterator, typename U>
@@ -669,7 +684,7 @@
         {
             // we have no means of testing whether the number is normalized if
             // the type is not float, double or long double
-            return call_n(sink, T(n), p);
+            return p.template call<real_inserter>(sink, T(n), p);
         }
 
 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)  
@@ -686,6 +701,7 @@
         call_n (OutputIterator& sink, U n, Policies const& p)
         {
         // prepare sign and get output format
+            bool force_sign = p.force_sign(n);
             bool sign_val = false;
             int flags = p.floatfield(n);
             if (detail::is_negative(n)) 
@@ -769,14 +785,13 @@
             }
 
         // generate integer part
-            bool r = p.template integer_part<force_sign>(
-                sink, long_int_part, sign_val);
+            bool r = p.integer_part(sink, long_int_part, sign_val, force_sign);
 
         // generate decimal point
-            r = r && p.dot(sink, long_frac_part);
+            r = r && p.dot(sink, long_frac_part, precision);
 
         // generate fractional part with the desired precision
-            r = r && p.fraction_part(sink, long_frac_part, prec);
+            r = r && p.fraction_part(sink, long_frac_part, prec, precision);
 
             if (r && 0 == (Policies::fmtflags::fixed & flags)) {
                 return p.template exponent<CharEncoding, Tag>(sink, 
Modified: trunk/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/int.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/int.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -200,8 +200,8 @@
         generate(OutputIterator& sink, Context&, Delimiter const& d
           , Attribute const& attr)
         {
-            return sign_inserter<force_sign>::call(sink
-                      , detail::is_zero(attr), detail::is_negative(attr)) &&
+            return sign_inserter::call(sink, detail::is_zero(attr)
+                      , detail::is_negative(attr), force_sign) &&
                    int_inserter<Radix, CharEncoding, Tag>::call(sink
                       , detail::absolute_value(attr)) &&
                    karma::delimit_out(sink, d);      // always do post-delimiting
@@ -262,8 +262,8 @@
             if (n_ != attr)
                 return false;
 
-            return sign_inserter<force_sign>::call(sink
-                      , detail::is_zero(n_), detail::is_negative(n_)) &&
+            return sign_inserter::call(sink, detail::is_zero(n_)
+                      , detail::is_negative(n_), force_sign) &&
                    int_inserter<Radix, CharEncoding, Tag>::call(sink
                       , detail::absolute_value(n_)) &&
                    karma::delimit_out(sink, d);      // always do post-delimiting
@@ -275,8 +275,8 @@
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , unused_type) const
         {
-            return sign_inserter<force_sign>::call(sink
-                      , detail::is_zero(n_), detail::is_negative(n_)) &&
+            return sign_inserter::call(sink, detail::is_zero(n_)
+                      , detail::is_negative(n_), force_sign) &&
                    int_inserter<Radix, CharEncoding, Tag>::call(sink
                       , detail::absolute_value(n_)) &&
                    karma::delimit_out(sink, d);      // always do post-delimiting
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -156,6 +156,8 @@
     struct any_real_generator
       : primitive_generator<any_real_generator<T, Policies, CharEncoding, Tag> >
     {
+        typedef typename Policies::properties properties;
+
         template <typename Context, typename Unused>
         struct attribute
         {
@@ -206,6 +208,8 @@
       : primitive_generator<literal_real_generator<T, Policies, CharEncoding
           , Tag, no_attribute> >
     {
+        typedef typename Policies::properties properties;
+
         template <typename Context, typename Unused>
         struct attribute
           : mpl::if_c<no_attribute, unused_type, T>
Modified: trunk/boost/spirit/home/karma/numeric/real_policies.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real_policies.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/real_policies.hpp	2009-08-14 16:25:02 EDT (Fri, 14 Aug 2009)
@@ -19,6 +19,8 @@
 #include <boost/spirit/home/karma/char.hpp>
 #include <boost/spirit/home/karma/numeric/int.hpp>
 
+#include <boost/mpl/bool.hpp>
+
 namespace boost { namespace spirit { namespace karma 
 {
     ///////////////////////////////////////////////////////////////////////////
@@ -50,6 +52,14 @@
         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.
         ///////////////////////////////////////////////////////////////////////
@@ -63,11 +73,38 @@
         BOOST_SCOPED_ENUM_END
 
         ///////////////////////////////////////////////////////////////////////
+        //  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' is specified as true, then all generated numbers will 
+        //  '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 const force_sign = false;
+        static bool const force_sign(T)
+        {
+            return false;
+        }
 
         ///////////////////////////////////////////////////////////////////////
         //  Return whether trailing zero digits have to be emitted in the 
@@ -135,16 +172,20 @@
         ///////////////////////////////////////////////////////////////////////
         //  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.
+        //      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
         ///////////////////////////////////////////////////////////////////////
-        template <bool ForceSign, typename OutputIterator>
-        static bool integer_part (OutputIterator& sink, T n, bool sign)
+        template <typename OutputIterator>
+        static bool integer_part (OutputIterator& sink, T n, bool sign
+          , bool force_sign)
         {
-            return sign_inserter<ForceSign>::call(
-                        sink, detail::is_zero(n), sign) &&
+            return sign_inserter::call(
+                      sink, detail::is_zero(n), sign, force_sign) &&
                    int_inserter<10>::call(sink, n);
         }
 
@@ -158,6 +199,8 @@
         //            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.
@@ -167,7 +210,7 @@
         //            function below.
         ///////////////////////////////////////////////////////////////////////
         template <typename OutputIterator>
-        static bool dot (OutputIterator& sink, T)
+        static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
         {
             return char_inserter<>::call(sink, '.');  // generate the dot by default 
         }
@@ -181,6 +224,10 @@
         //            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 
@@ -200,7 +247,7 @@
         ///////////////////////////////////////////////////////////////////////
         template <typename OutputIterator>
         static bool fraction_part (OutputIterator& sink, T n
-          , unsigned precision_)
+          , unsigned precision_, unsigned precision)
         {
             // allow for ADL to find the correct overload for floor and log10
             using namespace std;
@@ -213,7 +260,9 @@
             bool r = true;
             for (/**/; r && digits < precision_; digits = digits + 1)
                 r = char_inserter<>::call(sink, '0');
-            return r && int_inserter<10>::call(sink, n);
+            if (precision && r)
+                r = int_inserter<10>::call(sink, n);
+            return r;
         }
 
         ///////////////////////////////////////////////////////////////////////
@@ -234,8 +283,8 @@
         {
             long abs_n = detail::absolute_value(n);
             bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
-                     sign_inserter<false>::call(
-                          sink, detail::is_zero(n), detail::is_negative(n));
+                     sign_inserter::call(sink, detail::is_zero(n)
+                        , detail::is_negative(n), false);
 
             // the C99 Standard requires at least two digits in the exponent
             if (r && abs_n < 10)
@@ -247,8 +296,10 @@
         //  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. 
+        //      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 
@@ -258,23 +309,19 @@
         //  Note: These functions get called only if fpclassify() returned 
         //        FP_INFINITY or FP_NAN.
         ///////////////////////////////////////////////////////////////////////
-        template <
-            bool ForceSign, typename CharEncoding, typename Tag
-          , typename OutputIterator>
-        static bool nan (OutputIterator& sink, T n)
+        template <typename CharEncoding, typename Tag, typename OutputIterator>
+        static bool nan (OutputIterator& sink, T n, bool force_sign)
         {
-            return sign_inserter<ForceSign>::call(
-                        sink, false, detail::is_negative(n)) &&
+            return sign_inserter::call(
+                        sink, false, detail::is_negative(n), force_sign) &&
                    string_inserter<CharEncoding, Tag>::call(sink, "nan");
         }
 
-        template <
-            bool ForceSign, typename CharEncoding, typename Tag
-          , typename OutputIterator>
-        static bool inf (OutputIterator& sink, T n)
+        template <typename CharEncoding, typename Tag, typename OutputIterator>
+        static bool inf (OutputIterator& sink, T n, bool force_sign)
         {
-            return sign_inserter<ForceSign>::call(
-                        sink, false, detail::is_negative(n)) &&
+            return sign_inserter::call(
+                        sink, false, detail::is_negative(n), force_sign) &&
                    string_inserter<CharEncoding, Tag>::call(sink, "inf");
         }
     };