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