]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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) |