public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Patrick Palka <ppalka@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_chars patch Date: Wed, 22 Jul 2020 03:10:59 +0000 (GMT) [thread overview] Message-ID: <20200722031059.CDEB13844070@sourceware.org> (raw) https://gcc.gnu.org/g:f0bf15ce8dbe8573c1e194b5bd552c76a63366e7 commit f0bf15ce8dbe8573c1e194b5bd552c76a63366e7 Author: Patrick Palka <ppalka@redhat.com> Date: Tue Jul 21 22:45:37 2020 -0400 Minor changes to floating-point std::to_chars patch Diff: --- libstdc++-v3/config/abi/pre/gnu.ver | 6 +-- libstdc++-v3/src/c++17/floating_to_chars.cc | 82 ++++++++++++++++------------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index dbedd85068e..9be022d319a 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2305,13 +2305,13 @@ GLIBCXX_3.4.29 { _ZSt10from_charsPKcS0_R[def]St12chars_format; # std::to_chars(char*, char*, [float|double|long double]) - _ZSt8to_charsPcS_[fdeg]; + _ZSt8to_charsPcS_[defg]; # std::to_chars(char*, char*, [float|double|long double], chars_format) - _ZSt8to_charsPcS_[fdeg]St12chars_format; + _ZSt8to_charsPcS_[defg]St12chars_format; # std::to_chars(char*, char*, [float|double|long double], chars_format, int) - _ZSt8to_charsPcS_[fdeg]St12chars_formati; + _ZSt8to_charsPcS_[defg]St12chars_formati; } GLIBCXX_3.4.28; diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc index eb7cdf13e8b..d75e2e7d5b7 100644 --- a/libstdc++-v3/src/c++17/floating_to_chars.cc +++ b/libstdc++-v3/src/c++17/floating_to_chars.cc @@ -1,4 +1,4 @@ -// Floating-point std::to_chars implementation -*- C++ -*- +// std::to_chars implementation for floating-point types -*- C++ -*- // Copyright (C) 2020 Free Software Foundation, Inc. // @@ -385,9 +385,10 @@ namespace // The layout of __ibm128 isn't compatible with the standard IEEE format. // So we transform it into an IEEE-compatible format, suitable for // consumption by the generic Ryu API, with an 11-bit exponent and 105-bit - // mantissa (with an implicit leading bit). We keep the exponent and sign - // of the high part, and merge the mantissa of the high part with the - // mantissa (and the implicit leading bit) of the low part. + // mantissa (plus an implicit leading bit). We use the exponent and sign + // of the high part, and to form the mantissa we merge the mantissa of the + // high part with the mantissa (plus the implicit leading bit) of the low + // part. using uint_t = unsigned __int128; uint_t value_bits = 0; memcpy(&value_bits, &value, sizeof(value_bits)); @@ -480,9 +481,9 @@ namespace // 99999999999999991611392.0 has the shortest scientific form 1e23, so its // exact value is smaller than its shortest scientific form. // - // Usually we can trust the shortest scientific exponent to determine the - // length of the exact value, but for these powers of 10 the length of the - // exact value is one smaller than what the scientific exponent suggests. + // Usually we can rely on the shortest scientific exponent to determine the + // length of the exact fixed form, but for these powers of 10 the length of + // the fixed form is one less than what the scientific exponent suggests. // // This subroutine inspects a lookup table to detect when fd is such a // "rounded up" power of 10. @@ -552,6 +553,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (!str.empty()) { + // We're formatting +-inf or +-nan. if (!__builtin_signbit(value)) str.remove_prefix(strlen("-")); @@ -563,25 +565,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return {{first, errc{}}}; } + // We're formatting 0. __glibcxx_assert(value == 0); - const bool neg_zero_p = __builtin_signbit(value); - int output_length; + const bool sign = __builtin_signbit(value); + int expected_output_length; + const char* orig_first = first; switch (fmt) { case chars_format::fixed: case chars_format::scientific: case chars_format::hex: - output_length = neg_zero_p + 1; + expected_output_length = sign + 1; if (precision) - output_length += strlen(".") + precision; + expected_output_length += strlen(".") + precision; if (fmt == chars_format::scientific) - output_length += strlen("e+00"); + expected_output_length += strlen("e+00"); else if (fmt == chars_format::hex) - output_length += strlen("p+0"); - if (last - first < output_length) + expected_output_length += strlen("p+0"); + if (last - first < expected_output_length) return {{last, errc::value_too_large}}; - if (neg_zero_p) + if (sign) *first++ = '-'; *first++ = '0'; if (precision) @@ -600,20 +604,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION memcpy(first, "p+0", 3); first += 3; } - return {{first, errc{}}}; + break; default: __glibcxx_assert(fmt == chars_format::general || fmt == chars_format{}); - output_length = neg_zero_p + 1; - if (last - first < output_length) + expected_output_length = sign + 1; + if (last - first < expected_output_length) return {{last, errc::value_too_large}}; - if (neg_zero_p) + if (sign) *first++ = '-'; *first++ = '0'; - return {{first, errc{}}}; + break; } + __glibcxx_assert(first - orig_first == expected_output_length); + return {{first, errc{}}}; } // This subroutine of the floating-point to_chars overloads performs @@ -707,16 +713,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // before rounding is either 0 or 1, so it can't overflow. if constexpr (!has_implicit_leading_bit) { - // The only floating type with explicit leading mantissa bit - // that we currently support is x86 80-bit extended precision. - // So we hardcode the below overflow check for this type. + // The only supported floating-point type with explicit + // leading mantissa bit is LDK_FLOAT80, i.e. x86 80-bit + // extended precision, and so we hardcode the below overflow + // check+adjustment for this type. static_assert(mantissa_t_width == 64 && rounded_mantissa_bits == 64); if (effective_mantissa == 0) { // We rounded up the least significant nibble and the // mantissa overflowed, e.g f.fcp+10 with precision=1 - // became 10.0p+10. Absorb the extra hexit into the + // became 10.0p+10. Absorb this extra hexit into the // exponent to obtain 1.0p+14. effective_mantissa = mantissa_t{1} << (rounded_mantissa_bits - 4); @@ -771,20 +778,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Extract and mask out the leading nibble after the decimal point, // write its corresponding hexit, and repeat until the mantissa is // empty. - int nibble_offset = rounded_mantissa_bits - 4; + int nibble_offset = rounded_mantissa_bits; if constexpr (!has_implicit_leading_bit) // We already printed the entire leading hexit. nibble_offset -= 4; while (effective_mantissa != 0) { + nibble_offset -= 4; const unsigned nibble = effective_mantissa >> nibble_offset; __glibcxx_assert(nibble < 16); *first++ = "0123456789abcdef"[nibble]; ++written_hexits; - effective_mantissa &= ~(mantissa_t{0b1111} << nibble_offset); - nibble_offset -= 4; } + __glibcxx_assert(nibble_offset >= 0); __glibcxx_assert(written_hexits <= effective_precision); // Since the mantissa is now empty, every hexit hereafter must be '0'. if (int remaining_hexits = effective_precision - written_hexits) @@ -862,9 +869,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (mantissa_length > 1) expected_output_length += strlen("."); const int abs_exponent = abs(scientific_exponent); - expected_output_length += (abs_exponent >= 1000 ? strlen("e+NNNN") - : abs_exponent >= 100 ? strlen("e+NNN") - : strlen("e+NN")); + expected_output_length += (abs_exponent >= 1000 ? strlen("e+dddd") + : abs_exponent >= 100 ? strlen("e+ddd") + : strlen("e+dd")); if (last - first < expected_output_length) return {last, errc::value_too_large}; @@ -877,8 +884,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // The Ryu exponent is positive, and so this number's shortest // representation is a whole number, to be formatted in fixed instead // of scientific notation "as if by std::printf". This means we may - // need to print more digits of the IEEE mantissa that what the - // shortest scientific form given by Ryu contains. + // need to print more digits of the IEEE mantissa than what the + // shortest scientific form given by Ryu provides. // // For instance, the exactly representable number // 12300000000000001048576.0 has as its shortest scientific @@ -907,13 +914,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // log2 fd.mantissa + fd.exponent * log2 10 < mantissa_bits // where log2 10 is slightly smaller than 10/3=3.333... // - // Adding some wiggle room due to rounding yields the condition - // value_fits_inside_mantissa below. + // After adding some wiggle room due to rounding we get the condition + // value_fits_inside_mantissa_p below. const int log2_mantissa = __bit_width(fd.mantissa) - 1; - const bool value_fits_inside_mantissa + const bool value_fits_inside_mantissa_p = (log2_mantissa + (fd.exponent*10 + 2) / 3 < floating_type_traits<T>::mantissa_bits - 2); - if (value_fits_inside_mantissa) + if (value_fits_inside_mantissa_p) { // Print the small exactly-represantable number in fixed form by // writing out fd.mantissa followed by fd.exponent many 0s. @@ -993,8 +1000,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION *first++ = '-'; to_chars_result result = to_chars(first, last, fd.mantissa); __glibcxx_assert(result.ec == errc{}); - // Make space for and write the decimal point at the appropriate - // spot. + // Make space for and write the decimal point in the correct spot. memmove(&result.ptr[fd.exponent+1], &result.ptr[fd.exponent], -fd.exponent); result.ptr[fd.exponent] = '.';
next reply other threads:[~2020-07-22 3:10 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-07-22 3:10 Patrick Palka [this message] 2020-07-22 3:14 Patrick Palka
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200722031059.CDEB13844070@sourceware.org \ --to=ppalka@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).