From 96bb50348500f27ba39835504c98486c08cfffce Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 12 Apr 2023 14:46:48 +0200 Subject: [PATCH] Switch on precision rather than format [ci skip] --- src/to_chars.cpp | 84 +++++++++++++++++---------------------- test/to_chars_sprintf.cpp | 2 +- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/src/to_chars.cpp b/src/to_chars.cpp index 5679967..0633576 100644 --- a/src/to_chars.cpp +++ b/src/to_chars.cpp @@ -327,70 +327,58 @@ boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* la boost::charconv::to_chars_result boost::charconv::to_chars(char* first, char* last, double value, boost::charconv::chars_format fmt, int precision) noexcept { - - if (fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::fixed) + // Unspecified precision so we always go with shortest representation + if (precision == -1) { - const auto abs_value = std::abs(value); - if (abs_value >= 1 && abs_value < 1e16) + if (fmt == boost::charconv::chars_format::general || fmt == boost::charconv::chars_format::fixed) { - auto value_struct = jkj::dragonbox::to_decimal(value); - if (value_struct.is_negative) + const auto abs_value = std::abs(value); + if (abs_value >= 1 && abs_value < 1e18) // 1 x 10^(max_digits10 + 1) { - *first++ = '-'; - } + auto value_struct = jkj::dragonbox::to_decimal(value); + if (value_struct.is_negative) + { + *first++ = '-'; + } - auto r = boost::charconv::to_chars(first, last, value_struct.significand); - if (r.ec != 0) - { - return r; - } - - std::memmove(r.ptr + value_struct.exponent + 1, r.ptr + value_struct.exponent, -value_struct.exponent); - std::memset(r.ptr + value_struct.exponent, '.', 1); + auto r = boost::charconv::to_chars(first, last, value_struct.significand); + if (r.ec != 0) + { + return r; + } + + // Bounds check + if (value_struct.exponent < 0) + { + std::memmove(r.ptr + value_struct.exponent + 1, r.ptr + value_struct.exponent, -value_struct.exponent); + std::memset(r.ptr + value_struct.exponent, '.', 1); + } - return { r.ptr, 0 }; - } - else if (abs_value >= 1e16 && abs_value < 1e20) - { - if (value < 0) - { - *first++ = '-'; + return { r.ptr, 0 }; + } + else + { + auto* ptr = jkj::dragonbox::to_chars(value, first); + return { ptr, 0 }; } - return boost::charconv::to_chars(first, last, static_cast(abs_value)); } - else if (abs_value > 1e-288 && abs_value < 1e288) + else if (fmt == boost::charconv::chars_format::scientific) { auto* ptr = jkj::dragonbox::to_chars(value, first); return { ptr, 0 }; } - else + } + else + { + if (fmt != boost::charconv::chars_format::hex) { - if (precision == -1) - { - precision = std::numeric_limits::max_digits10 - 1; - } auto* ptr = boost::charconv::detail::floff(value, precision, first, fmt); return { ptr, 0 }; } } - else if (fmt == boost::charconv::chars_format::scientific) - { - if (precision == -1) - { - precision = std::numeric_limits::max_digits10; - } - if (precision > static_cast(last - first)) - { - return { first, EOVERFLOW }; - } - auto* ptr = boost::charconv::detail::floff(value, precision, first, fmt); - return { ptr, 0 }; - } - else if (fmt == boost::charconv::chars_format::hex) - { - return boost::charconv::detail::to_chars_hex(first, last, value, precision); - } - return { first + std::strlen(first), 0 }; + + // Hex handles both cases already + return boost::charconv::detail::to_chars_hex(first, last, value, precision); } boost::charconv::to_chars_result boost::charconv::to_chars( char* first, char* last, long double value ) noexcept diff --git a/test/to_chars_sprintf.cpp b/test/to_chars_sprintf.cpp index b657f82..a855b9d 100644 --- a/test/to_chars_sprintf.cpp +++ b/test/to_chars_sprintf.cpp @@ -67,7 +67,7 @@ char const* fmt_from_type_fixed( float ) char const* fmt_from_type( double ) { - return "%.17g"; + return "%g"; } char const* fmt_from_type_scientific( double )