From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1888) id C2A98385703F; Wed, 22 Jul 2020 03:14:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C2A98385703F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1595387664; bh=iQe3ne/hbce6zC01iRXMRrz3fU3T3pJ2Z+wQIMNfj6U=; h=From:To:Subject:Date:From; b=JHoLjlwYwr91FZKaKNMYHZBb/2Hm5auMWN259dHbWd5Fl4uhXPhzt9+VryJ3tCk5j mKNJcFo0BSngwQW6FRc5QyKcJ2BwVGO5DKrBnKTCYJL9SeM+MKJhqh/RHP1zLjb96T Mxaz/krLMU3ePEee+GKLUaSiSKjuMVgmCZPMYXpE= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Patrick Palka 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 X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/users/ppalka/heads/libstdcxx-floating-to_chars X-Git-Oldrev: de27f1fb70e1c65fb679bb742b37c4d3580d7752 X-Git-Newrev: 9cf480cd3c29b9d72b12a4a7e7068858a75da2c6 Message-Id: <20200722031424.C2A98385703F@sourceware.org> Date: Wed, 22 Jul 2020 03:14:24 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Jul 2020 03:14:24 -0000 https://gcc.gnu.org/g:9cf480cd3c29b9d72b12a4a7e7068858a75da2c6 commit 9cf480cd3c29b9d72b12a4a7e7068858a75da2c6 Author: Patrick Palka 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 | 79 +++++++++++++++-------------- 2 files changed, 45 insertions(+), 40 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..af7b3c7eff2 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,8 +385,8 @@ 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 (plus an implicit leading bit). We use the exponent and sign + // of the high part, and we merge the mantissa of the high part with the // mantissa (and the implicit leading bit) of the low part. using uint_t = unsigned __int128; uint_t value_bits = 0; @@ -480,9 +480,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 +552,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (!str.empty()) { + // We're formatting +-inf or +-nan. if (!__builtin_signbit(value)) str.remove_prefix(strlen("-")); @@ -563,25 +564,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 +603,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 +712,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 +777,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 +868,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 +883,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 +913,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::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 +999,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] = '.';