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/Makefile.in b/libstdc++-v3/src/c++17/Makefile.in index 2e71e31f3db..63984ecd52a 100644 --- a/libstdc++-v3/src/c++17/Makefile.in +++ b/libstdc++-v3/src/c++17/Makefile.in @@ -761,6 +761,10 @@ vpath % $(top_srcdir)/src/c++17 @GLIBCXX_LDBL_ALT128_COMPAT_TRUE@ $(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $< @GLIBCXX_LDBL_ALT128_COMPAT_TRUE@floating_from_chars.o: floating_from_chars.cc @GLIBCXX_LDBL_ALT128_COMPAT_TRUE@ $(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $< +@GLIBCXX_LDBL_ALT128_COMPAT_TRUE@floating_to_chars.lo: floating_to_chars.cc +@GLIBCXX_LDBL_ALT128_COMPAT_TRUE@ $(LTCXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $< +@GLIBCXX_LDBL_ALT128_COMPAT_TRUE@floating_to_chars.o: floating_to_chars.cc +@GLIBCXX_LDBL_ALT128_COMPAT_TRUE@ $(CXXCOMPILE) -mabi=ibmlongdouble $(LONG_DOUBLE_128_FLAGS) -c $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. 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 #include +#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 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 - { - 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 : floating_type_traits_binary128 + { }; #elif LONG_DOUBLE_KIND == LDK_IBM128 template<> struct floating_type_traits @@ -461,7 +497,8 @@ namespace else if constexpr (std::is_same_v) return ryu::floating_to_fd64(value); #ifdef __SIZEOF_INT128__ - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v + || std::is_same_v) { constexpr int mantissa_bits = floating_type_traits::mantissa_bits; @@ -815,6 +852,39 @@ template return result; } +namespace +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wabi" + template + 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) + 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 static to_chars_result __floating_to_chars_shortest(char* first, char* const last, const T value, @@ -926,7 +996,7 @@ template < floating_type_traits::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 __glibcxx_assert(output_length == expected_output_length); return result; } - else if constexpr (is_same_v) + else if constexpr (is_same_v + || is_same_v) { // 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 // 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