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)] libstdc++: Apply modifications to our local copy of Ryu
Date: Fri, 10 Jul 2020 21:48:46 +0000 (GMT)	[thread overview]
Message-ID: <20200710214847.010C5383E81D@sourceware.org> (raw)

https://gcc.gnu.org/g:ccaa6975f4888bf34affeec1f1b48a21168bb6fd

commit ccaa6975f4888bf34affeec1f1b48a21168bb6fd
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Jul 10 12:33:01 2020 -0400

    libstdc++: Apply modifications to our local copy of Ryu
    
    This performs the followin modifications to our local copy of Ryu in
    order to more easily use it for std::to_chars:
    
      * Remove all #includes
      * Remove copy_special_str routines
      * Adjust the exponent formatting to match printf
      * Remove some functions we're not going to use
      * Add an out-parameter to d2exp_buffered_n for the scientific exponent
      * Store the sign bit inside struct floating_decimal_[32|64]
      * Rename [df]2s_buffered_n and change their return type
    
    libstdc++-v3/ChangeLog:
    
            * src/c++17/ryu/common.h, src/c++17/ryu/d2fixed.c,
            src/c++17/ryu/d2fixed_full_table.h, src/c++17/ryu/d2s.c,
            src/c++17/ryu/d2s_intrinsics.h, src/c++17/ryu/f2s.c,
            src/c++17/ryu/f2s_intrinsics.h: Apply local modifications.

Diff:
---
 libstdc++-v3/src/c++17/ryu/common.h             | 19 -----
 libstdc++-v3/src/c++17/ryu/d2fixed.c            | 98 ++-----------------------
 libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h |  1 -
 libstdc++-v3/src/c++17/ryu/d2s.c                | 56 ++++----------
 libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h     |  4 -
 libstdc++-v3/src/c++17/ryu/f2s.c                | 52 ++++---------
 libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h     |  4 -
 7 files changed, 38 insertions(+), 196 deletions(-)

diff --git a/libstdc++-v3/src/c++17/ryu/common.h b/libstdc++-v3/src/c++17/ryu/common.h
index 7dc130947ac..f8ee147db04 100644
--- a/libstdc++-v3/src/c++17/ryu/common.h
+++ b/libstdc++-v3/src/c++17/ryu/common.h
@@ -17,9 +17,6 @@
 #ifndef RYU_COMMON_H
 #define RYU_COMMON_H
 
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
 
 #if defined(_M_IX86) || defined(_M_ARM)
 #define RYU_32_BIT_PLATFORM
@@ -83,22 +80,6 @@ static inline uint32_t log10Pow5(const int32_t e) {
   return (((uint32_t) e) * 732923) >> 20;
 }
 
-static inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
-  if (mantissa) {
-    memcpy(result, "NaN", 3);
-    return 3;
-  }
-  if (sign) {
-    result[0] = '-';
-  }
-  if (exponent) {
-    memcpy(result + sign, "Infinity", 8);
-    return sign + 8;
-  }
-  memcpy(result + sign, "0E0", 3);
-  return sign + 3;
-}
-
 static inline uint32_t float_to_bits(const float f) {
   uint32_t bits = 0;
   memcpy(&bits, &f, sizeof(float));
diff --git a/libstdc++-v3/src/c++17/ryu/d2fixed.c b/libstdc++-v3/src/c++17/ryu/d2fixed.c
index 5f479abb91b..642a29d3010 100644
--- a/libstdc++-v3/src/c++17/ryu/d2fixed.c
+++ b/libstdc++-v3/src/c++17/ryu/d2fixed.c
@@ -23,23 +23,11 @@
 //
 // -DRYU_AVOID_UINT128 Avoid using uint128_t. Slower, depending on your compiler.
 
-#include "ryu/ryu.h"
 
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
 
 #ifdef RYU_DEBUG
-#include <inttypes.h>
-#include <stdio.h>
 #endif
 
-#include "ryu/common.h"
-#include "ryu/digit_table.h"
-#include "ryu/d2fixed_full_table.h"
-#include "ryu/d2s_intrinsics.h"
 
 #define DOUBLE_MANTISSA_BITS 52
 #define DOUBLE_EXPONENT_BITS 11
@@ -328,33 +316,6 @@ static inline uint32_t lengthForIndex(const uint32_t idx) {
   return (log10Pow2(16 * (int32_t) idx) + 1 + 16 + 8) / 9;
 }
 
-static inline int copy_special_str_printf(char* const result, const bool sign, const uint64_t mantissa) {
-#if defined(_MSC_VER)
-  // TODO: Check that -nan is expected output on Windows.
-  if (sign) {
-    result[0] = '-';
-  }
-  if (mantissa) {
-    if (mantissa < (1ull << (DOUBLE_MANTISSA_BITS - 1))) {
-      memcpy(result + sign, "nan(snan)", 9);
-      return sign + 9;
-    }
-    memcpy(result + sign, "nan", 3);
-    return sign + 3;
-  }
-#else
-  if (mantissa) {
-    memcpy(result, "nan", 3);
-    return 3;
-  }
-  if (sign) {
-    result[0] = '-';
-  }
-#endif
-  memcpy(result + sign, "Infinity", 8);
-  return sign + 8;
-}
-
 int d2fixed_buffered_n(double d, uint32_t precision, char* result) {
   const uint64_t bits = double_to_bits(d);
 #ifdef RYU_DEBUG
@@ -372,20 +333,10 @@ int d2fixed_buffered_n(double d, uint32_t precision, char* result) {
 
   // Case distinction; exit early for the easy cases.
   if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u)) {
-    return copy_special_str_printf(result, ieeeSign, ieeeMantissa);
+    __builtin_abort();
   }
   if (ieeeExponent == 0 && ieeeMantissa == 0) {
-    int index = 0;
-    if (ieeeSign) {
-      result[index++] = '-';
-    }
-    result[index++] = '0';
-    if (precision > 0) {
-      result[index++] = '.';
-      memset(result + index, '0', precision);
-      index += precision;
-    }
-    return index;
+    __builtin_abort();
   }
 
   int32_t e2;
@@ -549,21 +500,9 @@ int d2fixed_buffered_n(double d, uint32_t precision, char* result) {
   return index;
 }
 
-void d2fixed_buffered(double d, uint32_t precision, char* result) {
-  const int len = d2fixed_buffered_n(d, precision, result);
-  result[len] = '\0';
-}
-
-char* d2fixed(double d, uint32_t precision) {
-  char* const buffer = (char*)malloc(2000);
-  const int index = d2fixed_buffered_n(d, precision, buffer);
-  buffer[index] = '\0';
-  return buffer;
-}
-
 
 
-int d2exp_buffered_n(double d, uint32_t precision, char* result) {
+int d2exp_buffered_n(double d, uint32_t precision, char* result, int* exp_out) {
   const uint64_t bits = double_to_bits(d);
 #ifdef RYU_DEBUG
   printf("IN=");
@@ -580,22 +519,10 @@ int d2exp_buffered_n(double d, uint32_t precision, char* result) {
 
   // Case distinction; exit early for the easy cases.
   if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u)) {
-    return copy_special_str_printf(result, ieeeSign, ieeeMantissa);
+    __builtin_abort();
   }
   if (ieeeExponent == 0 && ieeeMantissa == 0) {
-    int index = 0;
-    if (ieeeSign) {
-      result[index++] = '-';
-    }
-    result[index++] = '0';
-    if (precision > 0) {
-      result[index++] = '.';
-      memset(result + index, '0', precision);
-      index += precision;
-    }
-    memcpy(result + index, "e+00", 4);
-    index += 4;
-    return index;
+    __builtin_abort();
   }
 
   int32_t e2;
@@ -785,6 +712,9 @@ int d2exp_buffered_n(double d, uint32_t precision, char* result) {
       }
     }
   }
+  if (exp_out) {
+    *exp_out = exp;
+  }
   result[index++] = 'e';
   if (exp < 0) {
     result[index++] = '-';
@@ -805,15 +735,3 @@ int d2exp_buffered_n(double d, uint32_t precision, char* result) {
 
   return index;
 }
-
-void d2exp_buffered(double d, uint32_t precision, char* result) {
-  const int len = d2exp_buffered_n(d, precision, result);
-  result[len] = '\0';
-}
-
-char* d2exp(double d, uint32_t precision) {
-  char* const buffer = (char*)malloc(2000);
-  const int index = d2exp_buffered_n(d, precision, buffer);
-  buffer[index] = '\0';
-  return buffer;
-}
diff --git a/libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h b/libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h
index 70857652161..1fa252959e6 100644
--- a/libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h
+++ b/libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h
@@ -17,7 +17,6 @@
 #ifndef RYU_D2FIXED_FULL_TABLE_H
 #define RYU_D2FIXED_FULL_TABLE_H
 
-#include <stdint.h>
 
 #define TABLE_SIZE 64
 
diff --git a/libstdc++-v3/src/c++17/ryu/d2s.c b/libstdc++-v3/src/c++17/ryu/d2s.c
index aa0da52da71..3225808c463 100644
--- a/libstdc++-v3/src/c++17/ryu/d2s.c
+++ b/libstdc++-v3/src/c++17/ryu/d2s.c
@@ -27,28 +27,15 @@
 //     size by about 10x (only one case, and only double) at the cost of some
 //     performance. Currently requires MSVC intrinsics.
 
-#include "ryu/ryu.h"
 
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
 
 #ifdef RYU_DEBUG
-#include <inttypes.h>
-#include <stdio.h>
 #endif
 
-#include "ryu/common.h"
-#include "ryu/digit_table.h"
-#include "ryu/d2s_intrinsics.h"
 
 // Include either the small or the full lookup tables depending on the mode.
 #if defined(RYU_OPTIMIZE_SIZE)
-#include "ryu/d2s_small_table.h"
 #else
-#include "ryu/d2s_full_table.h"
 #endif
 
 #define DOUBLE_MANTISSA_BITS 52
@@ -86,9 +73,10 @@ typedef struct floating_decimal_64 {
   // Decimal exponent's range is -324 to 308
   // inclusive, and can fit in a short if needed.
   int32_t exponent;
+  bool sign;
 } floating_decimal_64;
 
-static inline floating_decimal_64 d2d(const uint64_t ieeeMantissa, const uint32_t ieeeExponent) {
+static inline floating_decimal_64 d2d(const uint64_t ieeeMantissa, const uint32_t ieeeExponent, const bool ieeeSign) {
   int32_t e2;
   uint64_t m2;
   if (ieeeExponent == 0) {
@@ -308,13 +296,14 @@ static inline floating_decimal_64 d2d(const uint64_t ieeeMantissa, const uint32_
   floating_decimal_64 fd;
   fd.exponent = exp;
   fd.mantissa = output;
+  fd.sign = ieeeSign;
   return fd;
 }
 
-static inline int to_chars(const floating_decimal_64 v, const bool sign, char* const result) {
+static inline int to_chars(const floating_decimal_64 v, char* const result) {
   // Step 5: Print the decimal representation.
   int index = 0;
-  if (sign) {
+  if (v.sign) {
     result[index++] = '-';
   }
 
@@ -397,29 +386,28 @@ static inline int to_chars(const floating_decimal_64 v, const bool sign, char* c
   }
 
   // Print the exponent.
-  result[index++] = 'E';
+  result[index++] = 'e';
   int32_t exp = v.exponent + (int32_t) olength - 1;
   if (exp < 0) {
     result[index++] = '-';
     exp = -exp;
-  }
+  } else
+    result[index++] = '+';
 
   if (exp >= 100) {
     const int32_t c = exp % 10;
     memcpy(result + index, DIGIT_TABLE + 2 * (exp / 10), 2);
     result[index + 2] = (char) ('0' + c);
     index += 3;
-  } else if (exp >= 10) {
+  } else {
     memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
     index += 2;
-  } else {
-    result[index++] = (char) ('0' + exp);
   }
 
   return index;
 }
 
-static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t ieeeExponent,
+static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t ieeeExponent, const bool ieeeSign,
   floating_decimal_64* const v) {
   const uint64_t m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
   const int32_t e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
@@ -448,10 +436,11 @@ static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t iee
   // Note: since 2^53 < 10^16, there is no need to adjust decimalLength17().
   v->mantissa = m2 >> -e2;
   v->exponent = 0;
+  v->sign = ieeeSign;
   return true;
 }
 
-int d2s_buffered_n(double f, char* result) {
+floating_decimal_64 floating_to_fd64(double f) {
   // Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
   const uint64_t bits = double_to_bits(f);
 
@@ -469,11 +458,11 @@ int d2s_buffered_n(double f, char* result) {
   const uint32_t ieeeExponent = (uint32_t) ((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
   // Case distinction; exit early for the easy cases.
   if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0)) {
-    return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+    __builtin_abort();
   }
 
   floating_decimal_64 v;
-  const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
+  const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, ieeeSign, &v);
   if (isSmallInt) {
     // For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros.
     // For scientific notation we need to move these zeros into the exponent.
@@ -489,21 +478,8 @@ int d2s_buffered_n(double f, char* result) {
       ++v.exponent;
     }
   } else {
-    v = d2d(ieeeMantissa, ieeeExponent);
+    v = d2d(ieeeMantissa, ieeeExponent, ieeeSign);
   }
 
-  return to_chars(v, ieeeSign, result);
-}
-
-void d2s_buffered(double f, char* result) {
-  const int index = d2s_buffered_n(f, result);
-
-  // Terminate the string.
-  result[index] = '\0';
-}
-
-char* d2s(double f) {
-  char* const result = (char*) malloc(25);
-  d2s_buffered(f, result);
-  return result;
+  return v;
 }
diff --git a/libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h b/libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h
index ea590a60d25..fa993e6fad6 100644
--- a/libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h
+++ b/libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h
@@ -17,11 +17,8 @@
 #ifndef RYU_D2S_INTRINSICS_H
 #define RYU_D2S_INTRINSICS_H
 
-#include <assert.h>
-#include <stdint.h>
 
 // Defines RYU_32_BIT_PLATFORM if applicable.
-#include "ryu/common.h"
 
 // ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined.
 // Let's do the same for now.
@@ -37,7 +34,6 @@ typedef __uint128_t uint128_t;
 
 #if defined(HAS_64_BIT_INTRINSICS)
 
-#include <intrin.h>
 
 static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
   return _umul128(a, b, productHi);
diff --git a/libstdc++-v3/src/c++17/ryu/f2s.c b/libstdc++-v3/src/c++17/ryu/f2s.c
index 255ecbe599c..5e635958aa1 100644
--- a/libstdc++-v3/src/c++17/ryu/f2s.c
+++ b/libstdc++-v3/src/c++17/ryu/f2s.c
@@ -18,22 +18,11 @@
 // Runtime compiler options:
 // -DRYU_DEBUG Generate verbose debugging output to stdout.
 
-#include "ryu/ryu.h"
 
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
 
 #ifdef RYU_DEBUG
-#include <stdio.h>
 #endif
 
-#include "ryu/common.h"
-#include "ryu/f2s_intrinsics.h"
-#include "ryu/digit_table.h"
 
 #define FLOAT_MANTISSA_BITS 23
 #define FLOAT_EXPONENT_BITS 8
@@ -45,9 +34,10 @@ typedef struct floating_decimal_32 {
   // Decimal exponent's range is -45 to 38
   // inclusive, and can fit in a short if needed.
   int32_t exponent;
+  bool sign;
 } floating_decimal_32;
 
-static inline floating_decimal_32 f2d(const uint32_t ieeeMantissa, const uint32_t ieeeExponent) {
+static inline floating_decimal_32 f2d(const uint32_t ieeeMantissa, const uint32_t ieeeExponent, const bool ieeeSign) {
   int32_t e2;
   uint32_t m2;
   if (ieeeExponent == 0) {
@@ -224,13 +214,14 @@ static inline floating_decimal_32 f2d(const uint32_t ieeeMantissa, const uint32_
   floating_decimal_32 fd;
   fd.exponent = exp;
   fd.mantissa = output;
+  fd.sign = ieeeSign;
   return fd;
 }
 
-static inline int to_chars(const floating_decimal_32 v, const bool sign, char* const result) {
+static inline int to_chars(const floating_decimal_32 v, char* const result) {
   // Step 5: Print the decimal representation.
   int index = 0;
-  if (sign) {
+  if (v.sign) {
     result[index++] = '-';
   }
 
@@ -288,24 +279,22 @@ static inline int to_chars(const floating_decimal_32 v, const bool sign, char* c
   }
 
   // Print the exponent.
-  result[index++] = 'E';
+  result[index++] = 'e';
   int32_t exp = v.exponent + (int32_t) olength - 1;
   if (exp < 0) {
     result[index++] = '-';
     exp = -exp;
-  }
-
-  if (exp >= 10) {
-    memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
-    index += 2;
   } else {
-    result[index++] = (char) ('0' + exp);
+    result[index++] = '+';
   }
 
+  memcpy(result + index, DIGIT_TABLE + 2 * exp, 2);
+  index += 2;
+
   return index;
 }
 
-int f2s_buffered_n(float f, char* result) {
+floating_decimal_32 floating_to_fd32(float f) {
   // Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
   const uint32_t bits = float_to_bits(f);
 
@@ -324,22 +313,9 @@ int f2s_buffered_n(float f, char* result) {
 
   // Case distinction; exit early for the easy cases.
   if (ieeeExponent == ((1u << FLOAT_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0)) {
-    return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+    __builtin_abort();
   }
 
-  const floating_decimal_32 v = f2d(ieeeMantissa, ieeeExponent);
-  return to_chars(v, ieeeSign, result);
-}
-
-void f2s_buffered(float f, char* result) {
-  const int index = f2s_buffered_n(f, result);
-
-  // Terminate the string.
-  result[index] = '\0';
-}
-
-char* f2s(float f) {
-  char* const result = (char*) malloc(16);
-  f2s_buffered(f, result);
-  return result;
+  const floating_decimal_32 v = f2d(ieeeMantissa, ieeeExponent, ieeeSign);
+  return v;
 }
diff --git a/libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h b/libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h
index bb822c9a0c0..db751a41329 100644
--- a/libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h
+++ b/libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h
@@ -18,18 +18,14 @@
 #define RYU_F2S_INTRINSICS_H
 
 // Defines RYU_32_BIT_PLATFORM if applicable.
-#include "ryu/common.h"
 
 #if defined(RYU_FLOAT_FULL_TABLE)
 
-#include "ryu/f2s_full_table.h"
 
 #else
 
 #if defined(RYU_OPTIMIZE_SIZE)
-#include "ryu/d2s_small_table.h"
 #else
-#include "ryu/d2s_full_table.h"
 #endif
 #define FLOAT_POW5_INV_BITCOUNT (DOUBLE_POW5_INV_BITCOUNT - 64)
 #define FLOAT_POW5_BITCOUNT (DOUBLE_POW5_BITCOUNT - 64)


             reply	other threads:[~2020-07-10 21:48 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-10 21:48 Patrick Palka [this message]
2020-07-14 19:45 Patrick Palka
2020-07-15 19:01 Patrick Palka
2020-07-17  4:27 Patrick Palka
2020-07-18  1:43 Patrick Palka
2020-07-20 14:27 Patrick Palka
2020-07-22  2:49 Patrick Palka
2020-07-22  3:10 Patrick Palka
2020-07-22 15:59 Patrick Palka
2020-11-18 14:22 Patrick Palka
2020-12-17 14:43 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=20200710214847.010C5383E81D@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: link
Be 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).