[committed] libstdc++: Define std::to_chars overloads for __ieee128 [PR 98389]

Jonathan Wakely jwakely@redhat.com
Wed Feb 24 17:00:47 GMT 2021


This adds overloads of std::to_chars for powerpc64's __ieee128, so that
std::to_chars can be used for long double when -mabi=ieeelongdouble is
in used.

Eventually we'll want to extend these new overloads to work for
__float128 on all targets that support that type. For now, we're only
doing it for powerpc64 when the new long double type is supported in
parallel to the old long double type.

Additionally the existing std::to_chars overloads for long double
are given the right symbol version, resolving PR libstdc++/98389.

libstdc++-v3/ChangeLog:

	PR libstdc++/98389
	* config/abi/pre/gnu.ver (GLIBCXX_3.4.29): Do not match to_chars
	symbols for long double arguments mangled as 'g'.
	* config/os/gnu-linux/ldbl-extra.ver: Likewise.
	* config/os/gnu-linux/ldbl-ieee128-extra.ver: Likewise.
	* src/c++17/Makefile.am [GLIBCXX_LDBL_ALT128_COMPAT_TRUE]:
	Use -mabi=ibmlongdouble for floating_to_chars.cc.
	* src/c++17/Makefile.in: Regenerate.
	* src/c++17/floating_to_chars.cc (floating_type_traits_binary128):
	New type defining type traits of IEEE binary128 format.
	(floating_type_traits<__float128>): Define specialization.
	(floating_type_traits<long double>): Define in terms of
	floating_type_traits_binary128 when appropriate.
	(floating_to_shortest_scientific): Handle __float128.
	(sprintf_ld): New function template for printing a long double
	or __ieee128 value using sprintf.
	(__floating_to_chars_shortest, __floating_to_chars_precision):
	Use sprintf_ld.
	(to_chars): Define overloads for __float128.

Tested powerpc64le-linux (with and without __ieee128 support in glibc)
and powerpc64-linux (big endian). Committed to trunk.

-------------- next part --------------
commit f90027d18a94d02ba8f3b7503c5f0835f432a89e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Feb 19 13:36:41 2021

    libstdc++: Define std::to_chars overloads for __ieee128 [PR 98389]
    
    This adds overloads of std::to_chars for powerpc64's __ieee128, so that
    std::to_chars can be used for long double when -mabi=ieeelongdouble is
    in used.
    
    Eventually we'll want to extend these new overloads to work for
    __float128 on all targets that support that type. For now, we're only
    doing it for powerpc64 when the new long double type is supported in
    parallel to the old long double type.
    
    Additionally the existing std::to_chars overloads for long double
    are given the right symbol version, resolving PR libstdc++/98389.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/98389
            * config/abi/pre/gnu.ver (GLIBCXX_3.4.29): Do not match to_chars
            symbols for long double arguments mangled as 'g'.
            * config/os/gnu-linux/ldbl-extra.ver: Likewise.
            * config/os/gnu-linux/ldbl-ieee128-extra.ver: Likewise.
            * src/c++17/Makefile.am [GLIBCXX_LDBL_ALT128_COMPAT_TRUE]:
            Use -mabi=ibmlongdouble for floating_to_chars.cc.
            * src/c++17/Makefile.in: Regenerate.
            * src/c++17/floating_to_chars.cc (floating_type_traits_binary128):
            New type defining type traits of IEEE binary128 format.
            (floating_type_traits<__float128>): Define specialization.
            (floating_type_traits<long double>): Define in terms of
            floating_type_traits_binary128 when appropriate.
            (floating_to_shortest_scientific): Handle __float128.
            (sprintf_ld): New function template for printing a long double
            or __ieee128 value using sprintf.
            (__floating_to_chars_shortest, __floating_to_chars_precision):
            Use sprintf_ld.
            (to_chars): Define overloads for __float128.

diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index d0c8066ce83..a2c151d11ac 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2394,11 +2394,11 @@ GLIBCXX_3.4.29 {
     _ZNSt9once_flag9_M_finishEb;
 
     # std::to_chars(char*, char*, [float|double|long double])
-    _ZSt8to_charsPcS_[defg];
+    _ZSt8to_charsPcS_[def];
     # std::to_chars(char*, char*, [float|double|long double], chars_format)
-    _ZSt8to_charsPcS_[defg]St12chars_format;
+    _ZSt8to_charsPcS_[def]St12chars_format;
     # std::to_chars(char*, char*, [float|double|long double], chars_format, int)
-    _ZSt8to_charsPcS_[defg]St12chars_formati;
+    _ZSt8to_charsPcS_[def]St12chars_formati;
 
 } GLIBCXX_3.4.28;
 
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver b/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
index b4f3af0f9d9..8c7c783ba58 100644
--- a/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
@@ -42,6 +42,7 @@ GLIBCXX_LDBL_3.4.21 {
 
 GLIBCXX_LDBL_3.4.29 {
   _ZSt10from_charsPKcS0_RgSt12chars_format;
+  _ZSt8to_charsPcS_g*;
 } GLIBCXX_LDBL_3.4.21;
 
 CXXABI_LDBL_1.3 {
diff --git a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
index 3c3395e4d4e..9b421b6f1f9 100644
--- a/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
+++ b/libstdc++-v3/config/os/gnu-linux/ldbl-ieee128-extra.ver
@@ -41,6 +41,7 @@ GLIBCXX_IEEE128_3.4.29 {
   _ZNKSt19__gnu_cxx11_ieee1289money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE3putES4_bRSt8ios_base[cw]u9__ieee128;
 
   _ZSt10from_charsPKcS0_Ru9__ieee128St12chars_format;
+  _ZSt8to_charsPcS_u9__ieee128*;
 
 } GLIBCXX_3.4.29;
 
diff --git a/libstdc++-v3/src/c++17/Makefile.am b/libstdc++-v3/src/c++17/Makefile.am
index 30759aeccb3..cb94aff5f1a 100644
--- a/libstdc++-v3/src/c++17/Makefile.am
+++ b/libstdc++-v3/src/c++17/Makefile.am
@@ -67,6 +67,10 @@ floating_from_chars.lo: floating_from_chars.cc
 	$(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
 floating_from_chars.o: floating_from_chars.cc
 	$(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+floating_to_chars.lo: floating_to_chars.cc
+	$(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
+floating_to_chars.o: floating_to_chars.cc
+	$(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $<
 endif
 
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc
index 4b2f85c1c1a..aea96e08df1 100644
--- a/libstdc++-v3/src/c++17/floating_to_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
@@ -40,6 +40,14 @@
 #include <string_view>
 #include <type_traits>
 
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+#ifndef __LONG_DOUBLE_IBM128__
+#error "floating_to_chars.cc must be compiled with -mabi=ibmlongdouble"
+#endif
+// sprintf for __ieee128
+extern "C" int __sprintfieee128(char*, const char*, ...);
+#endif
+
 // This implementation crucially assumes float/double have the
 // IEEE binary32/binary64 formats.
 #if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
@@ -67,11 +75,27 @@
 # elif __LDBL_MANT_DIG__ == 106
 #  define LONG_DOUBLE_KIND LDK_IBM128
 # endif
+# if defined _GLIBCXX_USE_FLOAT128 && __FLT128_MANT_DIG__ == 113
+// Define overloads of std::to_chars for __float128.
+#  define FLOAT128_TO_CHARS 1
+# endif
 #endif
+
 #if !defined(LONG_DOUBLE_KIND)
 # define LONG_DOUBLE_KIND LDK_UNSUPPORTED
 #endif
 
+// For now we only support __float128 when it's the powerpc64 __ieee128 type.
+#ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+# undef FLOAT128_TO_CHARS
+#endif
+
+#ifdef FLOAT128_TO_CHARS
+using F128_type = __float128;
+#else
+using F128_type = void;
+#endif
+
 namespace
 {
   namespace ryu
@@ -140,9 +164,107 @@ namespace
 	    0b0001010000011001011100100001010000010101101000001101000000000000 };
     };
 
+#if LONG_DOUBLE_KIND == LDK_BINARY128 || defined FLOAT128_TO_CHARS
+  // Traits for the IEEE binary128 format.
+  struct floating_type_traits_binary128
+  {
+    static constexpr int mantissa_bits = 112;
+    static constexpr int exponent_bits = 15;
+    static constexpr bool has_implicit_leading_bit = true;
+    using mantissa_t = unsigned __int128;
+    using shortest_scientific_t = ryu::floating_decimal_128;
+
+    static constexpr uint64_t pow10_adjustment_tab[]
+      = { 0b0000000000000000000000000000000000000000000000000100000010000000,
+	  0b1011001111110100000100010101101110011100100110000110010110011000,
+	  0b1010100010001101111111000000001101010010100010010000111011110111,
+	  0b1011111001110001111000011111000010110111000111110100101010100101,
+	  0b0110100110011110011011000011000010011001110001001001010011100011,
+	  0b0000011111110010101111101011101010000110011111100111001110100111,
+	  0b0100010101010110000010111011110100000010011001001010001110111101,
+	  0b1101110111000010001101100000110100000111001001101011000101011011,
+	  0b0100111011101101010000001101011000101100101110010010110000101011,
+	  0b0100000110111000000110101000010011101000110100010110000011101101,
+	  0b1011001101001000100001010001100100001111011101010101110001010110,
+	  0b1000000001000000101001110010110010001111101101010101001100000110,
+	  0b0101110110100110000110000001001010111110001110010000111111010011,
+	  0b1010001111100111000100011100100100111100100101000001011001000111,
+	  0b1010011000011100110101100111001011100101111111100001110100000100,
+	  0b1100011100100010100000110001001010000000100000001001010111011101,
+	  0b0101110000100011001111101101000000100110000010010111010001111010,
+	  0b0100111100011010110111101000100110000111001001101100000001111100,
+	  0b1100100100111110101011000100000101011010110111000111110100110101,
+	  0b0110010000010111010100110011000000111010000010111011010110000100,
+	  0b0101001001010010110111010111000101011100000111100111000001110010,
+	  0b1101111111001011101010110001000111011010111101001011010110100100,
+	  0b0001000100110000011111101011001101110010110110010000000011100100,
+	  0b0001000000000101001001001000000000011000100011001110101001001110,
+	  0b0010010010001000111010011011100001000110011011011110110100111000,
+	  0b0000100110101100000111100010100100011100110111011100001111001100,
+	  0b1011111010001110001100000011110111111111100000001011111111101100,
+	  0b0000011100001111010101110000100110111100101101110111101001000001,
+	  0b1100010001110110111100001001001101101000011100000010110101001011,
+	  0b0100101001101011111001011110101101100011011111011100101010101111,
+	  0b0001101001111001110000101101101100001011010001011110011101000010,
+	  0b1111000000101001101111011010110011101110100001011011001011100010,
+	  0b0101001010111101101100001111100010010110001101001000001101100100,
+	  0b0101100101011110001100101011111000111001111001001001101101100001,
+	  0b1111001101010010100100011011000110110010001111000111010001001101,
+	  0b0001110010011000000001000110110111011000011100001000011001110111,
+	  0b0100001011011011011011110011101100100101111111101100101000001110,
+	  0b0101011110111101010111100111101111000101111111111110100011011010,
+	  0b1110101010001001110100000010110111010111111010111110100110010110,
+	  0b1010001111100001001100101000110100001100011100110010000011010111,
+	  0b1111111101101111000100111100000101011000001110011011101010111001,
+	  0b1111101100001110100101111101011001000100000101110000110010100011,
+	  0b1001010110110101101101000101010001010000101011011111010011010000,
+	  0b0111001110110011101001100111000001000100001010110000010000001101,
+	  0b0101111100111110100111011001111001111011011110010111010011101010,
+	  0b1110111000000001100100111001100100110001011011001110101111110111,
+	  0b0001010001001101010111101010011111000011110001101101011001111111,
+	  0b0101000011100011010010001101100001011101011010100110101100100010,
+	  0b0001000101011000100101111100110110000101101101111000110001001011,
+	  0b0101100101001011011000010101000000010100011100101101000010011111,
+	  0b1000010010001011101001011010100010111011110100110011011000100111,
+	  0b1000011011100001010111010111010011101100100010010010100100101001,
+	  0b1001001001010111110101000010111010000000101111010100001010010010,
+	  0b0011011110110010010101111011000001000000000011011111000011111011,
+	  0b1011000110100011001110000001000100000001011100010111010010011110,
+	  0b0111101110110101110111110000011000000100011100011000101101101110,
+	  0b1001100101111011011100011110101011001111100111101010101010110111,
+	  0b1100110010010001100011001111010000000100011101001111011101001111,
+	  0b1000111001111010100101000010000100000001001100101010001011001101,
+	  0b0011101011110000110010100101010100110010100001000010101011111101,
+	  0b1100000000000110000010101011000000011101000110011111100010111111,
+	  0b0010100110000011011100010110111100010110101100110011101110001101,
+	  0b0010111101010011111000111001111100110111111100100011110001101110,
+	  0b1001110111001001101001001001011000010100110001000000100011010110,
+	  0b0011110101100111011011111100001000011001010100111100100101111010,
+	  0b0010001101000011000010100101110000010101101000100110000100001010,
+	  0b0010000010100110010101100101110011101111000111111111001001100001,
+	  0b0100111111011011011011100111111011000010011101101111011111110110,
+	  0b1111111111010110101011101000100101110100001110001001101011100111,
+	  0b1011111101000101110000111100100010111010100001010000010010110010,
+	  0b1111010101001011101011101010000100110110001110111100100110111111,
+	  0b1011001101000001001101000010101010010110010001100001011100011010,
+	  0b0101001011011101010001110100010000010001111100100100100001001101,
+	  0b0010100000111001100011000101100101000001111100111001101000000010,
+	  0b1011001111010101011001000100100110100100110111110100000110111000,
+	  0b0101011111010011100011010010111101110010100001111111100010001001,
+	  0b0010111011101100100000000000001111111010011101100111100001001101,
+	  0b1101000000000000000000000000000000000000000000000000000000000000 };
+  };
+
+# ifdef FLOAT128_TO_CHARS
+  template<>
+    struct floating_type_traits<__float128> : floating_type_traits_binary128
+    { };
+# endif
+#endif
+
 #if LONG_DOUBLE_KIND == LDK_BINARY64
   // When long double is equivalent to double, we just forward the long double
-  // overloads to the double overloads, so we don't need to define a a
+  // overloads to the double overloads, so we don't need to define a
   // floating_type_traits<long double> specialization in this case.
 #elif LONG_DOUBLE_KIND == LDK_FLOAT80
   template<>
@@ -236,94 +358,8 @@ namespace
     };
 #elif LONG_DOUBLE_KIND == LDK_BINARY128
   template<>
-    struct floating_type_traits<long double>
-    {
-      static constexpr int mantissa_bits = 112;
-      static constexpr int exponent_bits = 15;
-      static constexpr bool has_implicit_leading_bit = true;
-      using mantissa_t = unsigned __int128;
-      using shortest_scientific_t = ryu::floating_decimal_128;
-
-      static constexpr uint64_t pow10_adjustment_tab[]
-	= { 0b0000000000000000000000000000000000000000000000000100000010000000,
-	    0b1011001111110100000100010101101110011100100110000110010110011000,
-	    0b1010100010001101111111000000001101010010100010010000111011110111,
-	    0b1011111001110001111000011111000010110111000111110100101010100101,
-	    0b0110100110011110011011000011000010011001110001001001010011100011,
-	    0b0000011111110010101111101011101010000110011111100111001110100111,
-	    0b0100010101010110000010111011110100000010011001001010001110111101,
-	    0b1101110111000010001101100000110100000111001001101011000101011011,
-	    0b0100111011101101010000001101011000101100101110010010110000101011,
-	    0b0100000110111000000110101000010011101000110100010110000011101101,
-	    0b1011001101001000100001010001100100001111011101010101110001010110,
-	    0b1000000001000000101001110010110010001111101101010101001100000110,
-	    0b0101110110100110000110000001001010111110001110010000111111010011,
-	    0b1010001111100111000100011100100100111100100101000001011001000111,
-	    0b1010011000011100110101100111001011100101111111100001110100000100,
-	    0b1100011100100010100000110001001010000000100000001001010111011101,
-	    0b0101110000100011001111101101000000100110000010010111010001111010,
-	    0b0100111100011010110111101000100110000111001001101100000001111100,
-	    0b1100100100111110101011000100000101011010110111000111110100110101,
-	    0b0110010000010111010100110011000000111010000010111011010110000100,
-	    0b0101001001010010110111010111000101011100000111100111000001110010,
-	    0b1101111111001011101010110001000111011010111101001011010110100100,
-	    0b0001000100110000011111101011001101110010110110010000000011100100,
-	    0b0001000000000101001001001000000000011000100011001110101001001110,
-	    0b0010010010001000111010011011100001000110011011011110110100111000,
-	    0b0000100110101100000111100010100100011100110111011100001111001100,
-	    0b1011111010001110001100000011110111111111100000001011111111101100,
-	    0b0000011100001111010101110000100110111100101101110111101001000001,
-	    0b1100010001110110111100001001001101101000011100000010110101001011,
-	    0b0100101001101011111001011110101101100011011111011100101010101111,
-	    0b0001101001111001110000101101101100001011010001011110011101000010,
-	    0b1111000000101001101111011010110011101110100001011011001011100010,
-	    0b0101001010111101101100001111100010010110001101001000001101100100,
-	    0b0101100101011110001100101011111000111001111001001001101101100001,
-	    0b1111001101010010100100011011000110110010001111000111010001001101,
-	    0b0001110010011000000001000110110111011000011100001000011001110111,
-	    0b0100001011011011011011110011101100100101111111101100101000001110,
-	    0b0101011110111101010111100111101111000101111111111110100011011010,
-	    0b1110101010001001110100000010110111010111111010111110100110010110,
-	    0b1010001111100001001100101000110100001100011100110010000011010111,
-	    0b1111111101101111000100111100000101011000001110011011101010111001,
-	    0b1111101100001110100101111101011001000100000101110000110010100011,
-	    0b1001010110110101101101000101010001010000101011011111010011010000,
-	    0b0111001110110011101001100111000001000100001010110000010000001101,
-	    0b0101111100111110100111011001111001111011011110010111010011101010,
-	    0b1110111000000001100100111001100100110001011011001110101111110111,
-	    0b0001010001001101010111101010011111000011110001101101011001111111,
-	    0b0101000011100011010010001101100001011101011010100110101100100010,
-	    0b0001000101011000100101111100110110000101101101111000110001001011,
-	    0b0101100101001011011000010101000000010100011100101101000010011111,
-	    0b1000010010001011101001011010100010111011110100110011011000100111,
-	    0b1000011011100001010111010111010011101100100010010010100100101001,
-	    0b1001001001010111110101000010111010000000101111010100001010010010,
-	    0b0011011110110010010101111011000001000000000011011111000011111011,
-	    0b1011000110100011001110000001000100000001011100010111010010011110,
-	    0b0111101110110101110111110000011000000100011100011000101101101110,
-	    0b1001100101111011011100011110101011001111100111101010101010110111,
-	    0b1100110010010001100011001111010000000100011101001111011101001111,
-	    0b1000111001111010100101000010000100000001001100101010001011001101,
-	    0b0011101011110000110010100101010100110010100001000010101011111101,
-	    0b1100000000000110000010101011000000011101000110011111100010111111,
-	    0b0010100110000011011100010110111100010110101100110011101110001101,
-	    0b0010111101010011111000111001111100110111111100100011110001101110,
-	    0b1001110111001001101001001001011000010100110001000000100011010110,
-	    0b0011110101100111011011111100001000011001010100111100100101111010,
-	    0b0010001101000011000010100101110000010101101000100110000100001010,
-	    0b0010000010100110010101100101110011101111000111111111001001100001,
-	    0b0100111111011011011011100111111011000010011101101111011111110110,
-	    0b1111111111010110101011101000100101110100001110001001101011100111,
-	    0b1011111101000101110000111100100010111010100001010000010010110010,
-	    0b1111010101001011101011101010000100110110001110111100100110111111,
-	    0b1011001101000001001101000010101010010110010001100001011100011010,
-	    0b0101001011011101010001110100010000010001111100100100100001001101,
-	    0b0010100000111001100011000101100101000001111100111001101000000010,
-	    0b1011001111010101011001000100100110100100110111110100000110111000,
-	    0b0101011111010011100011010010111101110010100001111111100010001001,
-	    0b0010111011101100100000000000001111111010011101100111100001001101,
-	    0b1101000000000000000000000000000000000000000000000000000000000000 };
-    };
+    struct floating_type_traits<long double> : floating_type_traits_binary128
+    { };
 #elif LONG_DOUBLE_KIND == LDK_IBM128
   template<>
     struct floating_type_traits<long double>
@@ -461,7 +497,8 @@ namespace
       else if constexpr (std::is_same_v<T, double>)
 	return ryu::floating_to_fd64(value);
 #ifdef __SIZEOF_INT128__
-      else if constexpr (std::is_same_v<T, long double>)
+      else if constexpr (std::is_same_v<T, long double>
+			 || std::is_same_v<T, F128_type>)
 	{
 	  constexpr int mantissa_bits
 	    = floating_type_traits<T>::mantissa_bits;
@@ -815,6 +852,39 @@ template<typename T>
     return result;
   }
 
+namespace
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wabi"
+  template<typename T, typename... Extra>
+  inline int
+  sprintf_ld(char* buffer, const char* format_string, T value, Extra... args)
+  {
+    int len;
+
+#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
+    const int saved_rounding_mode = fegetround();
+    if (saved_rounding_mode != FE_TONEAREST)
+      fesetround(FE_TONEAREST); // We want round-to-nearest behavior.
+#endif
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+    if constexpr (is_same_v<T, __ieee128>)
+      len = __sprintfieee128(buffer, format_string, value, args...);
+    else
+#endif
+    len = sprintf(buffer, format_string, value, args...);
+
+#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
+    if (saved_rounding_mode != FE_TONEAREST)
+      fesetround(saved_rounding_mode);
+#endif
+
+    return len;
+  }
+#pragma GCC diagnostic pop
+}
+
 template<typename T>
   static to_chars_result
   __floating_to_chars_shortest(char* first, char* const last, const T value,
@@ -926,7 +996,7 @@ template<typename T>
 	     < floating_type_traits<T>::mantissa_bits - 2);
 	if (value_fits_inside_mantissa_p)
 	  {
-	    // Print the small exactly-represantable number in fixed form by
+	    // Print the small exactly-representable number in fixed form by
 	    // writing out fd.mantissa followed by fd.exponent many 0s.
 	    if (fd.sign)
 	      *first++ = '-';
@@ -938,26 +1008,18 @@ template<typename T>
 	    __glibcxx_assert(output_length == expected_output_length);
 	    return result;
 	  }
-	else if constexpr (is_same_v<T, long double>)
+	else if constexpr (is_same_v<T, long double>
+			   || is_same_v<T, F128_type>)
 	  {
 	    // We can't use d2fixed_buffered_n for types larger than double,
 	    // so we instead format larger types through sprintf.
 	    // TODO: We currently go through an intermediate buffer in order
-	    // to accomodate the mandatory null terminator of sprintf, but we
+	    // to accommodate the mandatory null terminator of sprintf, but we
 	    // can avoid this if we use sprintf to write all but the last
 	    // digit, and carefully compute and write the last digit
 	    // ourselves.
 	    char buffer[expected_output_length+1];
-#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
-	    const int saved_rounding_mode = fegetround();
-	    if (saved_rounding_mode != FE_TONEAREST)
-	      fesetround(FE_TONEAREST); // We want round-to-nearest behavior.
-#endif
-	    const int output_length = sprintf(buffer, "%.0Lf", value);
-#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
-	    if (saved_rounding_mode != FE_TONEAREST)
-	      fesetround(saved_rounding_mode);
-#endif
+	    const int output_length = sprintf_ld(buffer, "%.0Lf", value);
 	    __glibcxx_assert(output_length == expected_output_length);
 	    memcpy(first, buffer, output_length);
 	    return {first + output_length, errc{}};
@@ -1143,17 +1205,8 @@ template<typename T>
 
 	// Do the sprintf into the local buffer.
 	char buffer[output_length_upper_bound+1];
-#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
-	const int saved_rounding_mode = fegetround();
-	if (saved_rounding_mode != FE_TONEAREST)
-	  fesetround(FE_TONEAREST); // We want round-to-nearest behavior.
-#endif
 	int output_length
-	  = sprintf(buffer, output_specifier, effective_precision, value);
-#if _GLIBCXX_USE_C99_FENV_TR1 && defined(FE_TONEAREST)
-	if (saved_rounding_mode != FE_TONEAREST)
-	  fesetround(saved_rounding_mode);
-#endif
+	  = sprintf_ld(buffer, output_specifier, value, effective_precision);
 	__glibcxx_assert(output_length <= output_length_upper_bound);
 
 	if (effective_precision > 0)
@@ -1546,6 +1599,27 @@ to_chars(char* first, char* last, long double value, chars_format fmt,
     return __floating_to_chars_precision(first, last, value, fmt, precision);
 }
 
+#ifdef FLOAT128_TO_CHARS
+to_chars_result
+to_chars(char* first, char* last, __float128 value) noexcept
+{
+  return __floating_to_chars_shortest(first, last, value, chars_format{});
+}
+
+to_chars_result
+to_chars(char* first, char* last, __float128 value, chars_format fmt) noexcept
+{
+  return __floating_to_chars_shortest(first, last, value, fmt);
+}
+
+to_chars_result
+to_chars(char* first, char* last, __float128 value, chars_format fmt,
+	 int precision) noexcept
+{
+  return __floating_to_chars_precision(first, last, value, fmt, precision);
+}
+#endif
+
 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
 // Map the -mlong-double-64 long double overloads to the double overloads.
 extern "C" to_chars_result


More information about the Libstdc++ mailing list