Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/spirit/home/karma/numeric/real_policies.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/spirit/home/karma/numeric/real_policies.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,334 @@ +// Copyright (c) 2001-2011 Hartmut Kaiser +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM) +#define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/math/special_functions/fpclassify.hpp> +#include <boost/type_traits/remove_const.hpp> + +#include <boost/spirit/home/support/char_class.hpp> +#include <boost/spirit/home/karma/generator.hpp> +#include <boost/spirit/home/karma/char.hpp> +#include <boost/spirit/home/karma/numeric/int.hpp> +#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp> + +#include <boost/mpl/bool.hpp> + +namespace boost { namespace spirit { namespace karma +{ + /////////////////////////////////////////////////////////////////////////// + // + // real_policies, if you need special handling of your floating + // point numbers, just overload this policy class and use it as a template + // parameter to the karma::real_generator floating point specifier: + // + // template <typename T> + // struct scientific_policy : karma::real_policies<T> + // { + // // we want the numbers always to be in scientific format + // static int floatfield(T n) { return fmtflags::scientific; } + // }; + // + // typedef + // karma::real_generator<double, scientific_policy<double> > + // science_type; + // + // karma::generate(sink, science_type(), 1.0); // will output: 1.0e00 + // + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct real_policies + { + /////////////////////////////////////////////////////////////////////// + // Expose the data type the generator is targeted at + /////////////////////////////////////////////////////////////////////// + typedef T value_type; + + /////////////////////////////////////////////////////////////////////// + // By default the policy doesn't require any special iterator + // functionality. The floating point generator exposes its properties + // from here, so this needs to be updated in case other properties + // need to be implemented. + /////////////////////////////////////////////////////////////////////// + typedef mpl::int_<generator_properties::no_properties> properties; + + /////////////////////////////////////////////////////////////////////// + // Specifies, which representation type to use during output + // generation. + /////////////////////////////////////////////////////////////////////// + struct fmtflags + { + enum { + scientific = 0, // Generate floating-point values in scientific + // format (with an exponent field). + fixed = 1 // Generate floating-point values in fixed-point + // format (with no exponent field). + }; + }; + + /////////////////////////////////////////////////////////////////////// + // This is the main function used to generate the output for a + // floating point number. It is called by the real generator in order + // to perform the conversion. In theory all of the work can be + // implemented here, but it is the easiest to use existing + // functionality provided by the type specified by the template + // parameter `Inserter`. + // + // sink: the output iterator to use for generation + // n: the floating point number to convert + // p: the instance of the policy type used to instantiate this + // floating point generator. + /////////////////////////////////////////////////////////////////////// + template <typename Inserter, typename OutputIterator, typename Policies> + static bool + call (OutputIterator& sink, T n, Policies const& p) + { + return Inserter::call_n(sink, n, p); + } + + /////////////////////////////////////////////////////////////////////// + // The default behavior is to not to require generating a sign. If + // 'force_sign()' returns true, then all generated numbers will + // have a sign ('+' or '-', zeros will have a space instead of a sign) + // + // n The floating point number to output. This can be used to + // adjust the required behavior depending on the value of + // this number. + /////////////////////////////////////////////////////////////////////// + static bool force_sign(T) + { + return false; + } + + /////////////////////////////////////////////////////////////////////// + // Return whether trailing zero digits have to be emitted in the + // fractional part of the output. If set, this flag instructs the + // floating point generator to emit trailing zeros up to the required + // precision digits (as returned by the precision() function). + // + // n The floating point number to output. This can be used to + // adjust the required behavior depending on the value of + // this number. + /////////////////////////////////////////////////////////////////////// + static bool trailing_zeros(T) + { + // the default behavior is not to generate trailing zeros + return false; + } + + /////////////////////////////////////////////////////////////////////// + // Decide, which representation type to use in the generated output. + // + // By default all numbers having an absolute value of zero or in + // between 0.001 and 100000 will be generated using the fixed format, + // all others will be generated using the scientific representation. + // + // The function trailing_zeros() can be used to force the output of + // trailing zeros in the fractional part up to the number of digits + // returned by the precision() member function. The default is not to + // generate the trailing zeros. + // + // n The floating point number to output. This can be used to + // adjust the formatting flags depending on the value of + // this number. + /////////////////////////////////////////////////////////////////////// + static int floatfield(T n) + { + if (traits::test_zero(n)) + return fmtflags::fixed; + + T abs_n = traits::get_absolute_value(n); + return (abs_n >= 1e5 || abs_n < 1e-3) + ? fmtflags::scientific : fmtflags::fixed; + } + + /////////////////////////////////////////////////////////////////////// + // Return the maximum number of decimal digits to generate in the + // fractional part of the output. + // + // n The floating point number to output. This can be used to + // adjust the required precision depending on the value of + // this number. If the trailing zeros flag is specified the + // fractional part of the output will be 'filled' with + // zeros, if appropriate + // + // Note: If the trailing_zeros flag is not in effect additional + // comments apply. See the comment for the fraction_part() + // function below. Moreover, this precision will be limited + // to the value of std::numeric_limits<T>::digits10 + 1 + /////////////////////////////////////////////////////////////////////// + static unsigned precision(T) + { + // by default, generate max. 3 fractional digits + return 3; + } + + /////////////////////////////////////////////////////////////////////// + // Generate the integer part of the number. + // + // sink The output iterator to use for generation + // n The absolute value of the integer part of the floating + // point number to convert (always non-negative). + // sign The sign of the overall floating point number to + // convert. + // force_sign Whether a sign has to be generated even for + // non-negative numbers. Note, that force_sign will be + // set to false for zero floating point values. + /////////////////////////////////////////////////////////////////////// + template <typename OutputIterator> + static bool integer_part (OutputIterator& sink, T n, bool sign + , bool force_sign) + { + return sign_inserter::call( + sink, traits::test_zero(n), sign, force_sign, force_sign) && + int_inserter<10>::call(sink, n); + } + + /////////////////////////////////////////////////////////////////////// + // Generate the decimal point. + // + // sink The output iterator to use for generation + // n The fractional part of the floating point number to + // convert. Note that this number is scaled such, that + // it represents the number of units which correspond + // to the value returned from the precision() function + // earlier. I.e. a fractional part of 0.01234 is + // represented as 1234 when the 'Precision' is 5. + // precision The number of digits to emit as returned by the + // function 'precision()' above + // + // This is given to allow to decide, whether a decimal point + // has to be generated at all. + // + // Note: If the trailing_zeros flag is not in effect additional + // comments apply. See the comment for the fraction_part() + // function below. + /////////////////////////////////////////////////////////////////////// + template <typename OutputIterator> + static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/) + { + return char_inserter<>::call(sink, '.'); // generate the dot by default + } + + /////////////////////////////////////////////////////////////////////// + // Generate the fractional part of the number. + // + // sink The output iterator to use for generation + // n The fractional part of the floating point number to + // convert. This number is scaled such, that it represents + // the number of units which correspond to the 'Precision'. + // I.e. a fractional part of 0.01234 is represented as 1234 + // when the 'precision_' parameter is 5. + // precision_ The corrected number of digits to emit (see note + // below) + // precision The number of digits to emit as returned by the + // function 'precision()' above + // + // Note: If trailing_zeros() does not return true the 'precision_' + // parameter will have been corrected from the value the + // precision() function returned earlier (defining the maximal + // number of fractional digits) in the sense, that it takes into + // account trailing zeros. I.e. a floating point number 0.0123 + // and a value of 5 returned from precision() will result in: + // + // trailing_zeros is not specified: + // n 123 + // precision_ 4 + // + // trailing_zeros is specified: + // n 1230 + // precision_ 5 + // + /////////////////////////////////////////////////////////////////////// + template <typename OutputIterator> + static bool fraction_part (OutputIterator& sink, T n + , unsigned precision_, unsigned precision) + { + // allow for ADL to find the correct overload for floor and log10 + using namespace std; + + // The following is equivalent to: + // generate(sink, right_align(precision, '0')[ulong], n); + // but it's spelled out to avoid inter-modular dependencies. + + typename remove_const<T>::type digits = + (traits::test_zero(n) ? 0 : floor(log10(n))) + 1; + bool r = true; + for (/**/; r && digits < precision_; digits = digits + 1) + r = char_inserter<>::call(sink, '0'); + if (precision && r) + r = int_inserter<10>::call(sink, n); + return r; + } + + /////////////////////////////////////////////////////////////////////// + // Generate the exponential part of the number (this is called only + // if the floatfield() function returned the 'scientific' flag). + // + // sink The output iterator to use for generation + // n The (signed) exponential part of the floating point + // number to convert. + // + // The Tag template parameter is either of the type unused_type or + // describes the character class and conversion to be applied to any + // output possibly influenced by either the lower[...] or upper[...] + // directives. + /////////////////////////////////////////////////////////////////////// + template <typename CharEncoding, typename Tag, typename OutputIterator> + static bool exponent (OutputIterator& sink, long n) + { + long abs_n = traits::get_absolute_value(n); + bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') && + sign_inserter::call(sink, traits::test_zero(n) + , traits::test_negative(n), false); + + // the C99 Standard requires at least two digits in the exponent + if (r && abs_n < 10) + r = char_inserter<CharEncoding, Tag>::call(sink, '0'); + return r && int_inserter<10>::call(sink, abs_n); + } + + /////////////////////////////////////////////////////////////////////// + // Print the textual representations for non-normal floats (NaN and + // Inf) + // + // sink The output iterator to use for generation + // n The (signed) floating point number to convert. + // force_sign Whether a sign has to be generated even for + // non-negative numbers + // + // The Tag template parameter is either of the type unused_type or + // describes the character class and conversion to be applied to any + // output possibly influenced by either the lower[...] or upper[...] + // directives. + // + // Note: These functions get called only if fpclassify() returned + // FP_INFINITY or FP_NAN. + /////////////////////////////////////////////////////////////////////// + template <typename CharEncoding, typename Tag, typename OutputIterator> + static bool nan (OutputIterator& sink, T n, bool force_sign) + { + return sign_inserter::call( + sink, false, traits::test_negative(n), force_sign) && + string_inserter<CharEncoding, Tag>::call(sink, "nan"); + } + + template <typename CharEncoding, typename Tag, typename OutputIterator> + static bool inf (OutputIterator& sink, T n, bool force_sign) + { + return sign_inserter::call( + sink, false, traits::test_negative(n), force_sign) && + string_inserter<CharEncoding, Tag>::call(sink, "inf"); + } + }; +}}} + +#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)