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: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

* [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

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:10 [gcc(refs/users/ppalka/heads/libstdcxx-floating-to_chars)] Minor changes to floating-point std::to_chars patch Patrick Palka
2020-07-22  3:14 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).