real_policies.hpp 16 KB

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