PageRenderTime 30ms CodeModel.GetById 15ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/karma/numeric/real_policies.hpp

http://hadesmem.googlecode.com/
C++ Header | 333 lines | 109 code | 24 blank | 200 comment | 9 complexity | 7f69719e409cf59715c2ef103f8bfad7 MD5 | raw file
  1//  Copyright (c) 2001-2011 Hartmut Kaiser
  2// 
  3//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
  4//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5
  6#if !defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
  7#define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM
  8
  9#if defined(_MSC_VER)
 10#pragma once
 11#endif
 12
 13#include <boost/config/no_tr1/cmath.hpp>
 14#include <boost/math/special_functions/fpclassify.hpp>
 15#include <boost/type_traits/remove_const.hpp>
 16
 17#include <boost/spirit/home/support/char_class.hpp>
 18#include <boost/spirit/home/karma/generator.hpp>
 19#include <boost/spirit/home/karma/char.hpp>
 20#include <boost/spirit/home/karma/numeric/int.hpp>
 21#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
 22
 23#include <boost/mpl/bool.hpp>
 24
 25namespace boost { namespace spirit { namespace karma 
 26{
 27    ///////////////////////////////////////////////////////////////////////////
 28    //
 29    //  real_policies, if you need special handling of your floating
 30    //  point numbers, just overload this policy class and use it as a template
 31    //  parameter to the karma::real_generator floating point specifier:
 32    //
 33    //      template <typename T>
 34    //      struct scientific_policy : karma::real_policies<T>
 35    //      {
 36    //          //  we want the numbers always to be in scientific format
 37    //          static int floatfield(T n) { return fmtflags::scientific; }
 38    //      };
 39    //
 40    //      typedef 
 41    //          karma::real_generator<double, scientific_policy<double> > 
 42    //      science_type;
 43    //
 44    //      karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
 45    //
 46    ///////////////////////////////////////////////////////////////////////////
 47    template <typename T>
 48    struct real_policies
 49    {
 50        ///////////////////////////////////////////////////////////////////////
 51        // Expose the data type the generator is targeted at
 52        ///////////////////////////////////////////////////////////////////////
 53        typedef T value_type;
 54
 55        ///////////////////////////////////////////////////////////////////////
 56        //  By default the policy doesn't require any special iterator 
 57        //  functionality. The floating point generator exposes its properties
 58        //  from here, so this needs to be updated in case other properties
 59        //  need to be implemented.
 60        ///////////////////////////////////////////////////////////////////////
 61        typedef mpl::int_<generator_properties::no_properties> properties;
 62
 63        ///////////////////////////////////////////////////////////////////////
 64        //  Specifies, which representation type to use during output 
 65        //  generation.
 66        ///////////////////////////////////////////////////////////////////////
 67        struct fmtflags
 68        {
 69            enum {
 70                scientific = 0,   // Generate floating-point values in scientific 
 71                                  // format (with an exponent field).
 72                fixed = 1         // Generate floating-point values in fixed-point 
 73                                  // format (with no exponent field). 
 74            };
 75        };
 76
 77        ///////////////////////////////////////////////////////////////////////
 78        //  This is the main function used to generate the output for a 
 79        //  floating point number. It is called by the real generator in order 
 80        //  to perform the conversion. In theory all of the work can be 
 81        //  implemented here, but it is the easiest to use existing 
 82        //  functionality provided by the type specified by the template 
 83        //  parameter `Inserter`. 
 84        //
 85        //      sink: the output iterator to use for generation
 86        //      n:    the floating point number to convert 
 87        //      p:    the instance of the policy type used to instantiate this 
 88        //            floating point generator.
 89        ///////////////////////////////////////////////////////////////////////
 90        template <typename Inserter, typename OutputIterator, typename Policies>
 91        static bool
 92        call (OutputIterator& sink, T n, Policies const& p)
 93        {
 94            return Inserter::call_n(sink, n, p);
 95        }
 96
 97        ///////////////////////////////////////////////////////////////////////
 98        //  The default behavior is to not to require generating a sign. If 
 99        //  'force_sign()' returns true, then all generated numbers will 
100        //  have a sign ('+' or '-', zeros will have a space instead of a sign)
101        // 
102        //      n     The floating point number to output. This can be used to 
103        //            adjust the required behavior depending on the value of 
104        //            this number.
105        ///////////////////////////////////////////////////////////////////////
106        static bool force_sign(T)
107        {
108            return false;
109        }
110
111        ///////////////////////////////////////////////////////////////////////
112        //  Return whether trailing zero digits have to be emitted in the 
113        //  fractional part of the output. If set, this flag instructs the 
114        //  floating point generator to emit trailing zeros up to the required 
115        //  precision digits (as returned by the precision() function).
116        // 
117        //      n     The floating point number to output. This can be used to 
118        //            adjust the required behavior depending on the value of 
119        //            this number.
120        ///////////////////////////////////////////////////////////////////////
121        static bool trailing_zeros(T)
122        {
123            // the default behavior is not to generate trailing zeros
124            return false;
125        }
126
127        ///////////////////////////////////////////////////////////////////////
128        //  Decide, which representation type to use in the generated output.
129        //
130        //  By default all numbers having an absolute value of zero or in 
131        //  between 0.001 and 100000 will be generated using the fixed format, 
132        //  all others will be generated using the scientific representation.
133        //
134        //  The function trailing_zeros() can be used to force the output of 
135        //  trailing zeros in the fractional part up to the number of digits 
136        //  returned by the precision() member function. The default is not to 
137        //  generate the trailing zeros.
138        //  
139        //      n     The floating point number to output. This can be used to 
140        //            adjust the formatting flags depending on the value of 
141        //            this number.
142        ///////////////////////////////////////////////////////////////////////
143        static int floatfield(T n)
144        {
145            if (traits::test_zero(n))
146                return fmtflags::fixed;
147
148            T abs_n = traits::get_absolute_value(n);
149            return (abs_n >= 1e5 || abs_n < 1e-3) 
150              ? fmtflags::scientific : fmtflags::fixed;
151        }
152
153        ///////////////////////////////////////////////////////////////////////
154        //  Return the maximum number of decimal digits to generate in the 
155        //  fractional part of the output.
156        //  
157        //      n     The floating point number to output. This can be used to 
158        //            adjust the required precision depending on the value of 
159        //            this number. If the trailing zeros flag is specified the
160        //            fractional part of the output will be 'filled' with 
161        //            zeros, if appropriate
162        //
163        //  Note:     If the trailing_zeros flag is not in effect additional
164        //            comments apply. See the comment for the fraction_part()
165        //            function below. Moreover, this precision will be limited
166        //            to the value of std::numeric_limits<T>::digits10 + 1
167        ///////////////////////////////////////////////////////////////////////
168        static unsigned precision(T)
169        {
170            // by default, generate max. 3 fractional digits
171            return 3;
172        }
173
174        ///////////////////////////////////////////////////////////////////////
175        //  Generate the integer part of the number.
176        //
177        //      sink       The output iterator to use for generation
178        //      n          The absolute value of the integer part of the floating 
179        //                 point number to convert (always non-negative). 
180        //      sign       The sign of the overall floating point number to 
181        //                 convert.
182        //      force_sign Whether a sign has to be generated even for 
183        //                 non-negative numbers
184        ///////////////////////////////////////////////////////////////////////
185        template <typename OutputIterator>
186        static bool integer_part (OutputIterator& sink, T n, bool sign
187          , bool force_sign)
188        {
189            return sign_inserter::call(
190                      sink, traits::test_zero(n), sign, force_sign) &&
191                   int_inserter<10>::call(sink, n);
192        }
193
194        ///////////////////////////////////////////////////////////////////////
195        //  Generate the decimal point.
196        //
197        //      sink  The output iterator to use for generation
198        //      n     The fractional part of the floating point number to 
199        //            convert. Note that this number is scaled such, that 
200        //            it represents the number of units which correspond
201        //            to the value returned from the precision() function 
202        //            earlier. I.e. a fractional part of 0.01234 is
203        //            represented as 1234 when the 'Precision' is 5.
204        //      precision   The number of digits to emit as returned by the 
205        //                  function 'precision()' above
206        //
207        //            This is given to allow to decide, whether a decimal point
208        //            has to be generated at all.
209        //
210        //  Note:     If the trailing_zeros flag is not in effect additional
211        //            comments apply. See the comment for the fraction_part()
212        //            function below.
213        ///////////////////////////////////////////////////////////////////////
214        template <typename OutputIterator>
215        static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
216        {
217            return char_inserter<>::call(sink, '.');  // generate the dot by default 
218        }
219
220        ///////////////////////////////////////////////////////////////////////
221        //  Generate the fractional part of the number.
222        //
223        //      sink  The output iterator to use for generation
224        //      n     The fractional part of the floating point number to 
225        //            convert. This number is scaled such, that it represents 
226        //            the number of units which correspond to the 'Precision'. 
227        //            I.e. a fractional part of 0.01234 is represented as 1234 
228        //            when the 'precision_' parameter is 5.
229        //      precision_  The corrected number of digits to emit (see note 
230        //                  below)
231        //      precision   The number of digits to emit as returned by the 
232        //                  function 'precision()' above
233        //
234        //  Note: If trailing_zeros() does not return true the 'precision_' 
235        //        parameter will have been corrected from the value the 
236        //        precision() function returned earlier (defining the maximal 
237        //        number of fractional digits) in the sense, that it takes into 
238        //        account trailing zeros. I.e. a floating point number 0.0123 
239        //        and a value of 5 returned from precision() will result in:
240        //
241        //        trailing_zeros is not specified:
242        //            n           123
243        //            precision_  4
244        //
245        //        trailing_zeros is specified:
246        //            n           1230
247        //            precision_  5
248        //
249        ///////////////////////////////////////////////////////////////////////
250        template <typename OutputIterator>
251        static bool fraction_part (OutputIterator& sink, T n
252          , unsigned precision_, unsigned precision)
253        {
254            // allow for ADL to find the correct overload for floor and log10
255            using namespace std;
256
257            // The following is equivalent to:
258            //    generate(sink, right_align(precision, '0')[ulong], n);
259            // but it's spelled out to avoid inter-modular dependencies.
260
261            typename remove_const<T>::type digits = 
262                (traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
263            bool r = true;
264            for (/**/; r && digits < precision_; digits = digits + 1)
265                r = char_inserter<>::call(sink, '0');
266            if (precision && r)
267                r = int_inserter<10>::call(sink, n);
268            return r;
269        }
270
271        ///////////////////////////////////////////////////////////////////////
272        //  Generate the exponential part of the number (this is called only 
273        //  if the floatfield() function returned the 'scientific' flag).
274        //
275        //      sink  The output iterator to use for generation
276        //      n     The (signed) exponential part of the floating point 
277        //            number to convert. 
278        //
279        //  The Tag template parameter is either of the type unused_type or
280        //  describes the character class and conversion to be applied to any 
281        //  output possibly influenced by either the lower[...] or upper[...] 
282        //  directives.
283        ///////////////////////////////////////////////////////////////////////
284        template <typename CharEncoding, typename Tag, typename OutputIterator>
285        static bool exponent (OutputIterator& sink, long n)
286        {
287            long abs_n = traits::get_absolute_value(n);
288            bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
289                     sign_inserter::call(sink, traits::test_zero(n)
290                        , traits::test_negative(n), false);
291
292            // the C99 Standard requires at least two digits in the exponent
293            if (r && abs_n < 10)
294                r = char_inserter<CharEncoding, Tag>::call(sink, '0');
295            return r && int_inserter<10>::call(sink, abs_n);
296        }
297
298        ///////////////////////////////////////////////////////////////////////
299        //  Print the textual representations for non-normal floats (NaN and 
300        //  Inf)
301        //
302        //      sink       The output iterator to use for generation
303        //      n          The (signed) floating point number to convert. 
304        //      force_sign Whether a sign has to be generated even for 
305        //                 non-negative numbers
306        //
307        //  The Tag template parameter is either of the type unused_type or
308        //  describes the character class and conversion to be applied to any 
309        //  output possibly influenced by either the lower[...] or upper[...] 
310        //  directives.
311        //
312        //  Note: These functions get called only if fpclassify() returned 
313        //        FP_INFINITY or FP_NAN.
314        ///////////////////////////////////////////////////////////////////////
315        template <typename CharEncoding, typename Tag, typename OutputIterator>
316        static bool nan (OutputIterator& sink, T n, bool force_sign)
317        {
318            return sign_inserter::call(
319                        sink, false, traits::test_negative(n), force_sign) &&
320                   string_inserter<CharEncoding, Tag>::call(sink, "nan");
321        }
322
323        template <typename CharEncoding, typename Tag, typename OutputIterator>
324        static bool inf (OutputIterator& sink, T n, bool force_sign)
325        {
326            return sign_inserter::call(
327                        sink, false, traits::test_negative(n), force_sign) &&
328                   string_inserter<CharEncoding, Tag>::call(sink, "inf");
329        }
330    };
331}}}
332
333#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)