[gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_charn
Patrick Palka
ppalka@gcc.gnu.org
Wed Jul 22 02:49:53 GMT 2020
https://gcc.gnu.org/g:b937509c990b85114120ef90bbec78cf682a84de
commit b937509c990b85114120ef90bbec78cf682a84de
Author: Patrick Palka <ppalka@redhat.com>
Date: Tue Jul 21 22:45:37 2020 -0400
Minor changes to floating-point std::to_charn
Diff:
---
libstdc++-v3/config/abi/pre/gnu.ver | 6 +--
libstdc++-v3/src/c++17/floating_to_chars.cc | 67 ++++++++++++++++-------------
2 files changed, 40 insertions(+), 33 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..1e21d50c3c1 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,7 +481,7 @@ 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
+ // Usually we can rely on 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.
//
@@ -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
More information about the Libstdc++-cvs
mailing list