real_policies.hpp 16 KB

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