annotate DEPENDENCIES/generic/include/boost/spirit/home/karma/numeric/real_policies.hpp @ 133:4acb5d8d80b6 tip

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