/Src/Dependencies/Boost/boost/spirit/home/karma/numeric/real_policies.hpp

http://hadesmem.googlecode.com/ · C++ Header · 333 lines · 109 code · 24 blank · 200 comment · 9 complexity · 7f69719e409cf59715c2ef103f8bfad7 MD5 · raw file

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