public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_chars patch
@ 2020-07-22 3:14 Patrick Palka
0 siblings, 0 replies; 2+ messages in thread
From: Patrick Palka @ 2020-07-22 3:14 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:9cf480cd3c29b9d72b12a4a7e7068858a75da2c6
commit 9cf480cd3c29b9d72b12a4a7e7068858a75da2c6
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 | 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<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 +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] = '.';
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_chars patch
@ 2020-07-22 3:10 Patrick Palka
0 siblings, 0 replies; 2+ messages in thread
From: Patrick Palka @ 2020-07-22 3:10 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
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] = '.';
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-07-22 3:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-22 3:14 [gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_chars patch Patrick Palka
-- strict thread matches above, loose matches on Subject: below --
2020-07-22 3:10 Patrick Palka
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).