diff --git a/sprout/detail/float.hpp b/sprout/detail/float.hpp new file mode 100644 index 00000000..7eed9d5b --- /dev/null +++ b/sprout/detail/float.hpp @@ -0,0 +1,118 @@ +#ifndef SPROUT_DETAIL_FLOAT_HPP +#define SPROUT_DETAIL_FLOAT_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace detail { + // + // float_pow10 + // + template + inline SPROUT_CONSTEXPR FloatType + float_pow10_positive(int exponent) { + return exponent ? sprout::detail::float_pow10_positive(exponent - 1) * 10 + : FloatType(1) + ; + } + template + inline SPROUT_CONSTEXPR FloatType + float_pow10_negative(int exponent) { + return exponent ? sprout::detail::float_pow10_negative(exponent + 1) / 10 + : FloatType(1) + ; + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR FloatType + float_pow10(int exponent) { + return exponent < 0 + ? sprout::detail::float_pow10_negative(exponent) + : sprout::detail::float_pow10_positive(exponent) + ; + } + + // + // float_exponent10 + // + template + inline SPROUT_CONSTEXPR int + float_exponent10_positive(FloatType val) { + return val < 10 ? 0 + : 1 + sprout::detail::float_exponent10_positive(val / 10) + ; + } + template + inline SPROUT_CONSTEXPR int + float_exponent10_negative(FloatType val) { + return val < 1 ? 1 + sprout::detail::float_exponent10_negative(val * 10) + : 0 + ; + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + float_exponent10(FloatType val) { + return val < 0 + ? val > -1 + ? sprout::detail::float_exponent10_negative(-val) + : sprout::detail::float_exponent10_positive(-val) + : val < 1 + ? sprout::detail::float_exponent10_negative(val) + : sprout::detail::float_exponent10_positive(val) + ; + } + + // + // float_digits + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + float_digits_impl(FloatType val) { + return val < 1 ? 0 + : 1 + sprout::detail::float_digits_impl(val / 10) + ; + } + template + inline SPROUT_CONSTEXPR int + float_digits(FloatType val) { + return val < 0 + ? val > -1 ? 1 : 1 + sprout::detail::float_digits_impl(-val / 10) + : val < 1 ? 1 : 1 + sprout::detail::float_digits_impl(val / 10) + ; + } + + // + // float_digit_at + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + float_digit_of_impl(FloatType val) { + using std::floor; + return static_cast((val - floor(val)) * 10); + } + template + inline SPROUT_CONSTEXPR int + float_digit_at(FloatType val, int digits) { + return sprout::detail::float_digit_of_impl(val / sprout::detail::float_pow10(digits + 1)); + } + + // + // float_round_at + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR FloatType + float_round_impl(FloatType val, FloatType p10) { + using std::round; + return round(val * p10) / p10; + } + template + inline SPROUT_CONSTEXPR FloatType + float_round_at(FloatType val, int digits) { + return sprout::detail::float_round_impl(val, sprout::detail::float_pow10(digits)); + } + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_DETAIL_FLOAT_HPP diff --git a/sprout/string/float_to_string.hpp b/sprout/string/float_to_string.hpp index b4e7a909..b4e2be41 100644 --- a/sprout/string/float_to_string.hpp +++ b/sprout/string/float_to_string.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace sprout { namespace detail { @@ -27,64 +28,15 @@ namespace sprout { {}; namespace detail { - template - inline SPROUT_CONSTEXPR FloatType - float_pow10(int exponent) { - return exponent ? FloatType(10) * sprout::detail::float_pow10(exponent - 1) - : FloatType(1) - ; - } - - template - inline SPROUT_CONSTEXPR int - float_digits_impl(FloatType val) { - return !(val < 1 && val > -1) ? 1 + sprout::detail::float_digits_impl(val / 10) - : 0 - ; - } - template - inline SPROUT_CONSTEXPR int - float_digits(FloatType val) { - return !(val < 1 && val > -1) ? 1 + sprout::detail::float_digits_impl(val / 10) - : 1 - ; - } - - template - inline SPROUT_CONSTEXPR int - float_digit_of_impl(FloatType val) { - using std::floor; - return static_cast((val - floor(val)) * 10); - } - template - inline SPROUT_CONSTEXPR int - float_digit_of(FloatType val, int digits) { - return digits < 0 ? sprout::detail::float_digit_of_impl(val * sprout::detail::float_pow10(-digits - 1)) - : sprout::detail::float_digit_of_impl(val / sprout::detail::float_pow10(digits + 1)) - ; - } - - template - inline SPROUT_CONSTEXPR FloatType - float_round_impl(FloatType val, FloatType p10) { - using std::round; - return round(val * p10) / p10; - } - template - inline SPROUT_CONSTEXPR FloatType - float_round(FloatType val, int digits) { - return sprout::detail::float_round_impl(val, sprout::detail::float_pow10(digits)); - } - template inline SPROUT_CONSTEXPR sprout::basic_string::value> float_to_string(FloatType val, bool negative, int digits, sprout::index_tuple) { return negative ? sprout::basic_string::value>{ { static_cast('-'), - (Indexes < digits ? sprout::detail::int_to_char(sprout::detail::float_digit_of(val, digits - 1 - Indexes)) + (Indexes < digits ? sprout::detail::int_to_char(sprout::detail::float_digit_at(val, digits - 1 - Indexes)) : Indexes == digits ? static_cast('.') - : Indexes < digits + 1 + sprout::detail::decimal_places_length ? sprout::detail::int_to_char(sprout::detail::float_digit_of(val, digits - Indexes)) + : Indexes < digits + 1 + sprout::detail::decimal_places_length ? sprout::detail::int_to_char(sprout::detail::float_digit_at(val, digits - Indexes)) : Elem() )... }, @@ -92,9 +44,9 @@ namespace sprout { } : sprout::basic_string::value>{ { - (Indexes < digits ? sprout::detail::int_to_char(sprout::detail::float_digit_of(val, digits - 1 - Indexes)) + (Indexes < digits ? sprout::detail::int_to_char(sprout::detail::float_digit_at(val, digits - 1 - Indexes)) : Indexes == digits ? static_cast('.') - : Indexes < digits + 1 + sprout::detail::decimal_places_length ? sprout::detail::int_to_char(sprout::detail::float_digit_of(val, digits - Indexes)) + : Indexes < digits + 1 + sprout::detail::decimal_places_length ? sprout::detail::int_to_char(sprout::detail::float_digit_at(val, digits - Indexes)) : Elem() )... }, @@ -115,7 +67,7 @@ namespace sprout { inline SPROUT_CONSTEXPR sprout::basic_string::value> float_to_string(FloatType val) { return sprout::detail::float_to_string( - sprout::detail::float_round(val < 0 ? -val : val, sprout::detail::decimal_places_length), + sprout::detail::float_round_at(val < 0 ? -val : val, sprout::detail::decimal_places_length), val < 0, sprout::detail::float_digits(val), sprout::index_range<0, sprout::printed_float_digits::value - 1>::make()