📄 numeric_utils.hpp
字号:
{ template <typename T> static long call(T n, mpl::true_) { // this cast is safe since we know the result is not larger // than Radix return static_cast<long>(n % Radix); } template <typename T> static long call(T n, mpl::false_) { // Allow ADL to find the correct overload for fmod using namespace std; return cast_to_long::call(fmod(n, T(Radix))); } template <typename T> static long call(T n) { return call(n, mpl::bool_<is_integral<T>::value>()); } }; } // namespace detail /////////////////////////////////////////////////////////////////////////// // // The int_inserter template takes care of the integer to string // conversion. If specified, the loop is unrolled for better performance. // // Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in // between 0 (no unrolling) and the largest expected generated integer // string length (complete unrolling). // If not specified, this value defaults to 6. // ///////////////////////////////////////////////////////////////////////////#define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data) \ if (!detail::is_zero(n)) { \ int ch = radix_type::digit(remainder_type::call(n)); \ n = divide_type::call(n); \ /**/#define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data) \ *sink = ch; \ ++sink; \ } \ /**/ template <unsigned Radix, typename Tag = unused_type> struct int_inserter { typedef detail::radix_traits<Radix, Tag> radix_type; typedef detail::divide<Radix> divide_type; typedef detail::remainder<Radix> remainder_type; // Common code for integer string representations template <typename OutputIterator, typename T> static bool call(OutputIterator& sink, T n) { // remainder_type::call returns n % Radix int ch = radix_type::digit(remainder_type::call(n)); n = divide_type::call(n); BOOST_PP_REPEAT( BOOST_KARMA_NUMERICS_LOOP_UNROLL, BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _); if (!detail::is_zero(n)) call(sink, n); BOOST_PP_REPEAT( BOOST_KARMA_NUMERICS_LOOP_UNROLL, BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _); *sink = ch; ++sink; return true; } };#undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX#undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX /////////////////////////////////////////////////////////////////////////// // // The sign_inserter template generates a sign for a given numeric value. // // The parameter ForceSign allows to generate a sign even for positive // numbers. // /////////////////////////////////////////////////////////////////////////// template <bool ForceSign> struct sign_inserter { template <typename OutputIterator> static bool call(OutputIterator& sink, bool /*is_zero*/, bool is_negative) { // generate a sign for negative numbers only if (is_negative) { *sink = '-'; ++sink; } return true; } }; template <> struct sign_inserter<true> { template <typename OutputIterator> static bool call(OutputIterator& sink, bool is_zero, bool is_negative) { // generate a sign for all numbers except zero if (!is_zero) *sink = is_negative ? '-' : '+'; else *sink = ' '; ++sink; return true; } }; /////////////////////////////////////////////////////////////////////////// // These are helper functions for the real policies allowing to generate // a single character and a string /////////////////////////////////////////////////////////////////////////// template <typename Tag = unused_type> struct char_inserter { template <typename OutputIterator, typename Char> static bool call(OutputIterator& sink, Char c) { return detail::generate_to(sink, c, Tag()); } }; template <typename Tag = unused_type> struct string_inserter { template <typename OutputIterator, typename String> static bool call(OutputIterator& sink, String str) { return detail::string_generate(sink, str, Tag()); } }; /////////////////////////////////////////////////////////////////////////// // // The real_inserter template takes care of the floating point number to // string conversion. The RealPolicies template parameter is used to allow // customization of the formatting process // /////////////////////////////////////////////////////////////////////////// template <typename T, typename RealPolicies, typename Tag = unused_type> struct real_inserter { enum { force_sign = RealPolicies::force_sign }; template <typename OutputIterator> static bool call (OutputIterator& sink, float n, RealPolicies const& p) { int fpclass = boost::math::fpclassify(n); if (FP_NAN == fpclass) return RealPolicies::template nan<force_sign, Tag>(sink, n); else if (FP_INFINITE == fpclass) return RealPolicies::template inf<force_sign, Tag>(sink, n); return call_n(sink, n, p); } template <typename OutputIterator> static bool call (OutputIterator& sink, double n, RealPolicies const& p) { int fpclass = boost::math::fpclassify(n); if (FP_NAN == fpclass) return RealPolicies::template nan<force_sign, Tag>(sink, n); else if (FP_INFINITE == fpclass) return RealPolicies::template inf<force_sign, Tag>(sink, n); return call_n(sink, n, p); } template <typename OutputIterator> static bool call (OutputIterator& sink, long double n, RealPolicies const& p) { int fpclass = boost::math::fpclassify(n); if (FP_NAN == fpclass) return RealPolicies::template nan<force_sign, Tag>(sink, n); else if (FP_INFINITE == fpclass) return RealPolicies::template inf<force_sign, Tag>(sink, n); return call_n(sink, n, p); } template <typename OutputIterator, typename U> static bool call (OutputIterator& sink, U n, RealPolicies const& p) { // we have no means of testing whether the number is normalized if // the type is not float, double or long double return call_n(sink, T(n), p); } #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning(push) # pragma warning(disable: 4100) // 'p': unreferenced formal parameter # pragma warning(disable: 4127) // conditional expression is constant#endif /////////////////////////////////////////////////////////////////////// // This is the workhorse behind the real generator /////////////////////////////////////////////////////////////////////// template <typename OutputIterator, typename U> static bool call_n (OutputIterator& sink, U n, RealPolicies const& p) { // prepare sign and get output format bool sign_val = false; int flags = p.floatfield(n); if (detail::is_negative(n)) { n = -n; sign_val = true; } // The scientific representation requires the normalization of the // value to convert. // allow for ADL to find the correct overloads for log10 et.al. using namespace std; U dim = 0; if (0 == (p.fixed & flags) && !detail::is_zero(n)) { dim = log10(n); if (dim > 0) n /= pow(U(10.0), (int)detail::round_to_long::call(dim)); else if (n < 1.) n *= pow(U(10.0), (int)detail::round_to_long::call(-dim)); } // prepare numbers (sign, integer and fraction part) unsigned precision = p.precision(n); U integer_part; U precexp = std::pow(10.0, (int)precision); U fractional_part = modf(n, &integer_part); fractional_part = floor(fractional_part * precexp + 0.5); if (fractional_part >= precexp) { fractional_part -= precexp; integer_part += 1; // handle rounding overflow } // if trailing zeros are to be omitted, normalize the precision and // fractional part U long_int_part = floor(integer_part); U long_frac_part = floor(fractional_part); if (!p.trailing_zeros) { if (0 != long_frac_part) { // remove the trailing zeros while (0 != precision && 0 == detail::remainder<10>::call(long_frac_part)) { long_frac_part = detail::divide<10>::call(long_frac_part); --precision; } } else { // if the fractional part is zero, we don't need to output // any additional digits precision = 0; } } // call the actual generating functions to output the different parts if (sign_val && detail::is_zero(long_int_part) && detail::is_zero(long_frac_part)) { sign_val = false; // result is zero, no sign please } // generate integer part bool r = p.template integer_part<force_sign>( sink, long_int_part, sign_val); // generate decimal point r = r && p.dot(sink, long_frac_part); // generate fractional part with the desired precision r = r && p.fraction_part(sink, long_frac_part, precision); if (r && 0 == (p.fixed & flags)) { return p.template exponent<Tag>(sink, detail::round_to_long::call(dim)); } return r; }#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning(pop) #endif };}}}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -