libstdc++: Apply modifications to our local copy of Ryu
authorPatrick Palka <ppalka@redhat.com>
Fri, 18 Dec 2020 04:11:15 +0000 (23:11 -0500)
committerPatrick Palka <ppalka@redhat.com>
Fri, 18 Dec 2020 04:11:15 +0000 (23:11 -0500)
This performs the following modifications to our local copy of Ryu in
order to make it more readily usable for our std::to_chars
implementation:

  * 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
  * Make generic_binary_to_decimal take the bit representation in parts

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, src/c++17/ryu/generic_128.c:
Apply local modifications.

libstdc++-v3/src/c++17/ryu/common.h
libstdc++-v3/src/c++17/ryu/d2fixed.c
libstdc++-v3/src/c++17/ryu/d2fixed_full_table.h
libstdc++-v3/src/c++17/ryu/d2s.c
libstdc++-v3/src/c++17/ryu/d2s_intrinsics.h
libstdc++-v3/src/c++17/ryu/f2s.c
libstdc++-v3/src/c++17/ryu/f2s_intrinsics.h
libstdc++-v3/src/c++17/ryu/generic_128.c

index 7dc130947ac797284cb23194abaf11b0a76000a4..f8ee147db042849fb37b57187cda0023efc438a4 100644 (file)
@@ -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));
index 5f479abb91bdff11b258516a4818863839e7292e..642a29d30105fc909815a59eed6b6475908f10af 100644 (file)
 //
 // -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;
-}
index 7085765216139b93bf38bc433590102de2c0acc2..1fa252959e6bf9cc0abd2d01ae90dd6b16dc8a90 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef RYU_D2FIXED_FULL_TABLE_H
 #define RYU_D2FIXED_FULL_TABLE_H
 
-#include <stdint.h>
 
 #define TABLE_SIZE 64
 
index aa0da52da71a71e594da0333fb487676b4500aa8..3225808c463ddca258bf2ebf7202830dd26a90a7 100644 (file)
 //     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;
 }
index ea590a60d252a137b03175821db007e30e3c85d5..fa993e6fad664564a0c01199a4bee9707794a315 100644 (file)
 #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);
index 255ecbe599ca95898c63f6c74616bf14130533a5..5e635958aa19d9ee61629ec94f7bed9a2fc1115f 100644 (file)
 // 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;
 }
index bb822c9a0c005cd09a16ebee3a63e66e70fd2cb7..db751a41329776588386453d0ff6976bcdb29735 100644 (file)
 #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)
index 2eb8da8aba8f49df4113cdde9fe4a3ac3f2ff5b9..17c1567a6a11226e246c2abc057f89129bd04795 100644 (file)
@@ -37,42 +37,9 @@ static char* s(uint128_t v) {
 
 #define ONE ((uint128_t) 1)
 
-#define FLOAT_MANTISSA_BITS 23
-#define FLOAT_EXPONENT_BITS 8
-
-struct floating_decimal_128 float_to_fd128(float f) {
-  uint32_t bits = 0;
-  memcpy(&bits, &f, sizeof(float));
-  return generic_binary_to_decimal(bits, FLOAT_MANTISSA_BITS, FLOAT_EXPONENT_BITS, false);
-}
-
-#define DOUBLE_MANTISSA_BITS 52
-#define DOUBLE_EXPONENT_BITS 11
-
-struct floating_decimal_128 double_to_fd128(double d) {
-  uint64_t bits = 0;
-  memcpy(&bits, &d, sizeof(double));
-  return generic_binary_to_decimal(bits, DOUBLE_MANTISSA_BITS, DOUBLE_EXPONENT_BITS, false);
-}
-
-#define LONG_DOUBLE_MANTISSA_BITS 64
-#define LONG_DOUBLE_EXPONENT_BITS 15
-
-struct floating_decimal_128 long_double_to_fd128(long double d) {
-  uint128_t bits = 0;
-  memcpy(&bits, &d, sizeof(long double));
-#ifdef RYU_DEBUG
-  // For some odd reason, this ends up with noise in the top 48 bits. We can
-  // clear out those bits with the following line; this is not required, the
-  // conversion routine should ignore those bits, but the debug output can be
-  // confusing if they aren't 0s.
-  bits &= (ONE << 80) - 1;
-#endif
-  return generic_binary_to_decimal(bits, LONG_DOUBLE_MANTISSA_BITS, LONG_DOUBLE_EXPONENT_BITS, true);
-}
-
 struct floating_decimal_128 generic_binary_to_decimal(
-    const uint128_t bits, const uint32_t mantissaBits, const uint32_t exponentBits, const bool explicitLeadingBit) {
+    const uint128_t ieeeMantissa, const uint32_t ieeeExponent, const bool ieeeSign,
+    const uint32_t mantissaBits, const uint32_t exponentBits, const bool explicitLeadingBit) {
 #ifdef RYU_DEBUG
   printf("IN=");
   for (int32_t bit = 127; bit >= 0; --bit) {
@@ -82,9 +49,6 @@ struct floating_decimal_128 generic_binary_to_decimal(
 #endif
 
   const uint32_t bias = (1u << (exponentBits - 1)) - 1;
-  const bool ieeeSign = ((bits >> (mantissaBits + exponentBits)) & 1) != 0;
-  const uint128_t ieeeMantissa = bits & ((ONE << mantissaBits) - 1);
-  const uint32_t ieeeExponent = (uint32_t) ((bits >> mantissaBits) & ((ONE << exponentBits) - 1u));
 
   if (ieeeExponent == 0 && ieeeMantissa == 0) {
     struct floating_decimal_128 fd;
@@ -320,14 +284,17 @@ int generic_to_chars(const struct floating_decimal_128 v, char* const result) {
   }
 
   // Print the exponent.
-  result[index++] = 'E';
+  result[index++] = 'e';
   int32_t exp = v.exponent + olength - 1;
   if (exp < 0) {
     result[index++] = '-';
     exp = -exp;
-  }
+  } else
+    result[index++] = '+';
 
   uint32_t elength = decimalLength(exp);
+  if (elength == 1)
+    ++elength;
   for (uint32_t i = 0; i < elength; ++i) {
     const uint32_t c = exp % 10;
     exp /= 10;