]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/karma/numeric/real_policies.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / karma / numeric / real_policies.hpp
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
25 namespace 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. Note, that force_sign will be
184 // set to false for zero floating point values.
185 ///////////////////////////////////////////////////////////////////////
186 template <typename OutputIterator>
187 static bool integer_part (OutputIterator& sink, T n, bool sign
188 , bool force_sign)
189 {
190 return sign_inserter::call(
191 sink, traits::test_zero(n), sign, force_sign, force_sign) &&
192 int_inserter<10>::call(sink, n);
193 }
194
195 ///////////////////////////////////////////////////////////////////////
196 // Generate the decimal point.
197 //
198 // sink The output iterator to use for generation
199 // n The fractional part of the floating point number to
200 // convert. Note that this number is scaled such, that
201 // it represents the number of units which correspond
202 // to the value returned from the precision() function
203 // earlier. I.e. a fractional part of 0.01234 is
204 // represented as 1234 when the 'Precision' is 5.
205 // precision The number of digits to emit as returned by the
206 // function 'precision()' above
207 //
208 // This is given to allow to decide, whether a decimal point
209 // has to be generated at all.
210 //
211 // Note: If the trailing_zeros flag is not in effect additional
212 // comments apply. See the comment for the fraction_part()
213 // function below.
214 ///////////////////////////////////////////////////////////////////////
215 template <typename OutputIterator>
216 static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
217 {
218 return char_inserter<>::call(sink, '.'); // generate the dot by default
219 }
220
221 ///////////////////////////////////////////////////////////////////////
222 // Generate the fractional part of the number.
223 //
224 // sink The output iterator to use for generation
225 // n The fractional part of the floating point number to
226 // convert. This number is scaled such, that it represents
227 // the number of units which correspond to the 'Precision'.
228 // I.e. a fractional part of 0.01234 is represented as 1234
229 // when the 'precision_' parameter is 5.
230 // precision_ The corrected number of digits to emit (see note
231 // below)
232 // precision The number of digits to emit as returned by the
233 // function 'precision()' above
234 //
235 // Note: If trailing_zeros() does not return true the 'precision_'
236 // parameter will have been corrected from the value the
237 // precision() function returned earlier (defining the maximal
238 // number of fractional digits) in the sense, that it takes into
239 // account trailing zeros. I.e. a floating point number 0.0123
240 // and a value of 5 returned from precision() will result in:
241 //
242 // trailing_zeros is not specified:
243 // n 123
244 // precision_ 4
245 //
246 // trailing_zeros is specified:
247 // n 1230
248 // precision_ 5
249 //
250 ///////////////////////////////////////////////////////////////////////
251 template <typename OutputIterator>
252 static bool fraction_part (OutputIterator& sink, T n
253 , unsigned precision_, unsigned precision)
254 {
255 // allow for ADL to find the correct overload for floor and log10
256 using namespace std;
257
258 // The following is equivalent to:
259 // generate(sink, right_align(precision, '0')[ulong], n);
260 // but it's spelled out to avoid inter-modular dependencies.
261
262 typename remove_const<T>::type digits =
263 (traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
264 bool r = true;
265 for (/**/; r && digits < precision_; digits = digits + 1)
266 r = char_inserter<>::call(sink, '0');
267 if (precision && r)
268 r = int_inserter<10>::call(sink, n);
269 return r;
270 }
271
272 ///////////////////////////////////////////////////////////////////////
273 // Generate the exponential part of the number (this is called only
274 // if the floatfield() function returned the 'scientific' flag).
275 //
276 // sink The output iterator to use for generation
277 // n The (signed) exponential part of the floating point
278 // number to convert.
279 //
280 // The Tag template parameter is either of the type unused_type or
281 // describes the character class and conversion to be applied to any
282 // output possibly influenced by either the lower[...] or upper[...]
283 // directives.
284 ///////////////////////////////////////////////////////////////////////
285 template <typename CharEncoding, typename Tag, typename OutputIterator>
286 static bool exponent (OutputIterator& sink, long n)
287 {
288 long abs_n = traits::get_absolute_value(n);
289 bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
290 sign_inserter::call(sink, traits::test_zero(n)
291 , traits::test_negative(n), false);
292
293 // the C99 Standard requires at least two digits in the exponent
294 if (r && abs_n < 10)
295 r = char_inserter<CharEncoding, Tag>::call(sink, '0');
296 return r && int_inserter<10>::call(sink, abs_n);
297 }
298
299 ///////////////////////////////////////////////////////////////////////
300 // Print the textual representations for non-normal floats (NaN and
301 // Inf)
302 //
303 // sink The output iterator to use for generation
304 // n The (signed) floating point number to convert.
305 // force_sign Whether a sign has to be generated even for
306 // non-negative numbers
307 //
308 // The Tag template parameter is either of the type unused_type or
309 // describes the character class and conversion to be applied to any
310 // output possibly influenced by either the lower[...] or upper[...]
311 // directives.
312 //
313 // Note: These functions get called only if fpclassify() returned
314 // FP_INFINITY or FP_NAN.
315 ///////////////////////////////////////////////////////////////////////
316 template <typename CharEncoding, typename Tag, typename OutputIterator>
317 static bool nan (OutputIterator& sink, T n, bool force_sign)
318 {
319 return sign_inserter::call(
320 sink, false, traits::test_negative(n), force_sign) &&
321 string_inserter<CharEncoding, Tag>::call(sink, "nan");
322 }
323
324 template <typename CharEncoding, typename Tag, typename OutputIterator>
325 static bool inf (OutputIterator& sink, T n, bool force_sign)
326 {
327 return sign_inserter::call(
328 sink, false, traits::test_negative(n), force_sign) &&
329 string_inserter<CharEncoding, Tag>::call(sink, "inf");
330 }
331 };
332 }}}
333
334 #endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)