diff mbox

[v3,4/8] float128: Add public _Float128 declarations to libm.

Message ID 1494355732-26039-1-git-send-email-gftg@linux.vnet.ibm.com
State New
Headers show

Commit Message

Gabriel F. T. Gomes May 9, 2017, 6:48 p.m. UTC
From: "Paul E. Murphy" <murphyp@linux.vnet.ibm.com>

Changes since v2:

  - Refactored the macros that enable support for float128 in the
    library to __HAVE_FLOAT128 and __HAVE_DISTINCT_FLOAT128.
  - Enabled declarations of functions protected by IEC_60559_BFP_TYPES
    when IEC_60559_TYPES_EXT is defined.
  - Do not define L in a public header.
  - Fixed comment about __builtin_huge_valf128.
  - Fixed Copyright years.

-- 8< --
This introduces the machine-dependent bits/floatn.h to control
the inclusion of _Float128 ABI.

	* bits/floatn.h: New file.
	* bits/floatn-compat.h: Likewise.
	* bits/huge_val_flt128.h: Likewise.

	* bits/libm-simd-decl-stubs.h (__DECL_SIMD_cosf128): New macro.
	(__DECL_SIMD_sinf128): Likewise.
	(__DECL_SIMD_sincosf128): Likewise.
	(__DECL_SIMD_logf128): Likewise.
	(__DECL_SIMD_expf128): Likewise.
	(__DECL_SIMD_powf128): Likewise.

	* math/Makefile (headers): Install bits/floatn.h,
	bits/floatn-compat.h and bits/huge_val_flt128.h.

	* math/bits/cmathcalls.h (_Mdouble_complex_): Only define if not
	defined.

	* math/mathcalls.h (drem): Only define if __FLOATN_TYPE
	not defined.
	(gamma): Likewise.
	(nexttoward): Likewise.
	(significand): Likewise.
	(pow10): Likewise.
	(scalb): Likewise.
	(finite): Likewise.
	(isinf): Likewise.
	(isnan): Likewise.

	* math/complex.h: Include bits/cmathcalls.h to get the declarations
	of float128 versions of complex functions.
	[__HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)] (CMPLXF128):
	Define macro.

	* math/math.h: Define and undefine __FLOATN_TYPE as
	needed for _FloatN types. Add prototypes for _Float128.
	[__HAVE_DISTINCT_FLOAT128] (isinf): This builtin is broken for
	_Float128 type on GCC < 7.0.  Explicitly call __isinff128 for
	_Float128 type and GCC < 7.0, otherwise use the builtin.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(__f128): New macro to apply proper _Float128 literal suffix
	depending on compiler version for __USE_GNU enabled constants.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_Ef128): New _GNU_SOURCE enabled macro.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_LOG2Ef128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_LOG10Ef128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_LN2f128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_LN10f128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_PIf128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_PI_2f128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_PI_4f128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_1_PIf128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_2_PIf128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_SQRT2f128): Likewise.
	[__HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)]
	(M_SQRT1_2f128): Likewise.

	* sysdeps/powerpc/powerpc64/bits/floatn-compat.h: New file to
	localize workarounds for old compilers.
---
 bits/floatn-compat.h                             | 20 ++++++++
 bits/floatn.h                                    | 30 ++++++++++++
 bits/huge_val_flt128.h                           | 23 +++++++++
 bits/libm-simd-decl-stubs.h                      |  6 +++
 math/Makefile                                    |  3 +-
 math/bits/cmathcalls.h                           |  4 +-
 math/bits/mathcalls.h                            | 36 +++++++++-----
 math/complex.h                                   | 27 ++++++++++-
 math/math.h                                      | 61 +++++++++++++++++++++++-
 sysdeps/powerpc/powerpc64le/bits/floatn-compat.h | 57 ++++++++++++++++++++++
 10 files changed, 250 insertions(+), 17 deletions(-)
 create mode 100644 bits/floatn-compat.h
 create mode 100644 bits/floatn.h
 create mode 100644 bits/huge_val_flt128.h
 create mode 100644 sysdeps/powerpc/powerpc64le/bits/floatn-compat.h

Comments

Joseph Myers May 9, 2017, 10:56 p.m. UTC | #1
I don't see patch 7 in this patch set.  When resending a patch series, 
please make the resent series self-contained, even if some patches didn't 
get changed.  (And really it would be best to say patch N/5 rather than /8 
if the first three patches are now in, so no longer part of the new 
series.)

On Tue, 9 May 2017, Gabriel F. T. Gomes wrote:

> +# ifndef __FLOATN_TYPE

The preferred convention where possible is macros defined to nonzero or 0, 
rather than defined/undefined.  So for consistency with 
__MATH_DECLARING_DOUBLE, I think you should have a macro 
__MATH_DECLARING_FLOATN, defined to 1 when bits/mathcalls.h (etc.) is 
included for _Float128, 0 when it is included for float / double / long 
double.

I think this patch is a better place than patch 8 to include the 
definition of SNANF128.

> +/* Include the file of declarations again, this time using `_Float128'
> +   instead of `double' and appending f128 to each function name.  */
> +
> +#if __HAVE_DISTINCT_FLOAT128

That's not the right logically condition for when to declare (subject to 
__GLIBC_USE (IEC_60559_TYPES_EXT)) most functions.  I think 
__HAVE_FLOAT128 && !defined _LIBC might be better, by analogy with the 
conditions for declaring long double functions.  (long double tests 
_LIBC_TEST as well, but _LIBC_TEST use ought to be obsolete after Zack's 
patch to avoid internal declarations, including _LIBC, for most of the 
testsuite).

> +# include <bits/mathcalls-helper-functions.h>

Then, you'd add a test for __HAVE_DISTINCT_FLOAT128 around this include.

> +# if __GLIBC_USE (IEC_60559_TYPES_EXT)
> +#  include <bits/mathcalls.h>
> +# endif

And this one would stay as-is.

> +#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT) && defined __USE_GNU
> +# if defined __GNUC__ && !__GNUC_PREREQ (7,0)
> +#  define __f128(x) x ## q
> +# else
> +#  define __f128(x) x ## f128
> +# endif

__USE_GNU implies __GLIBC_USE (IEC_60559_TYPES_EXT), so you don't need to 
test the latter here.

You have a default #undef of __CFLOAT128 in bits/floatn.h, but __f128 in 
math.h and __L in bits/floatn-compat.h.  We should have a coherent design 
for where the definitions of helper macros such as __CFLOAT128 and __f128 
go.  I wonder about the following:

* bits/floatn.h defines __f128 (when _Float128 is supported) to the 
definition concatenating f128 as a suffix.  The default bits/floatn.h 
would need a comment about this (but no definition).  It defines 
__CFLOAT128 to _Complex _Float128 when _Float128 is supported (the default 
is #undef when _Float128 is not supported) - not just for old compilers.

* bits/floatn-compat.h gives a #error if bits/floatn.h hasn't already been 
included.  It defines such things as __builtin_huge_valf128 that need 
overriding for old compilers.  In the old compiler case, it undefines and 
redefines __f128 and __CFLOAT128.  For the new compiler case, it has 
nothing to do.  __L disappears (replaced by __f128).

You also need to make headers that need bits/floatn-compat.h include it; I 
don't see any #includes of bits/floatn-compat.h in this patch.

Or maybe nothing actually requires bits/floatn.h and bits/floatn-compat.h 
to be separate and all the definitions should just go in bits/floatn.h 
unless and until there are two architectures that need different versions 
of one of the headers but the same version of the other.  That would avoid 
various places needing to #include bits/floatn-compat.h, and avoid the 
need to get includes in the correct order.

> diff --git a/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h

I think this file would better be in one of the patches actually adding 
support on powerpc rather than in the present series, but I may as well 
review the contents now.

> new file mode 100644
> index 0000000..7a711a8
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h

GCC supports a range of multilib configurations with both BE and LE 
libraries for powerpc64.

In such configurations, the same headers are shared between multilibs.  So 
you can't have a separate version of an installed header for powerpc64le.  
Instead, you need to have one header with appropriate preprocessor 
conditionals that express that _Float128 is supported for powerpc64le, but 
not for BE.  And it would go in sysdeps/powerpc so all powerpc 
configurations get that same header installed.

> +#if __HAVE_FLOAT128
> +
> +/* The type _Float128, as well as the literal suffix (F128), exist for powerpc
> +   only since GCC 7.0.  */
> +# if !__GNUC_PREREQ (7, 0)
> +#  define __L(x) x##Q
> +typedef __float128 _Float128;
> +# else
> +#  define __L(x) x##F128
> +# endif

As noted, combine with __f128.

> +/* Add a typedef for older GCC compilers which don't natively support
> +   _Complex _Float128.  */
> +# if !__GNUC_PREREQ (7, 0) && !defined __CFLOAT128
> +typedef _Complex float __cfloat128 __attribute__ ((mode (KC)));

This is not namespace-clean; you need to use __mode__ (__KC__).

> +/* __builtin_signbit is type generic in GCC 6.2, which is the minimum
> +   version required for float128 support on powerpc64le.  */
> +# define __builtin_signbitf128 __builtin_signbit

I think a better approach would be to have math.h use type-generic 
__builtin_signbit (without __MATH_TG) if __GNUC_PREREQ (6,0).  Then 
nothing will ever try to call __builtin_signbitf128, because bits/floatn.h 
won't declare any _Float128 support for GCC versions without type-generic 
__builtin_signbit, and so __MATH_TG will be defined for such versions 
without _Float128 support.
Joseph Myers May 10, 2017, 11:43 a.m. UTC | #2
On Tue, 9 May 2017, Joseph Myers wrote:

> > +/* Include the file of declarations again, this time using `_Float128'
> > +   instead of `double' and appending f128 to each function name.  */
> > +
> > +#if __HAVE_DISTINCT_FLOAT128
> 
> That's not the right logically condition for when to declare (subject to 
> __GLIBC_USE (IEC_60559_TYPES_EXT)) most functions.  I think 
> __HAVE_FLOAT128 && !defined _LIBC might be better, by analogy with the 
> conditions for declaring long double functions.  (long double tests 
> _LIBC_TEST as well, but _LIBC_TEST use ought to be obsolete after Zack's 
> patch to avoid internal declarations, including _LIBC, for most of the 
> testsuite).

Correction:

If there's a distinct _Float128, the functions should be declared, both 
inside and outside libc.  If it exists but is not distinct, they should 
only be declared outside libc.  So:

#if __HAVE_DISTINCT_FLOAT128 || (__HAVE_FLOAT128 && !defined _LIBC)

should be right.

Also, for the patch where bits/floatn.h is added for powerpc64le: note 
that GCC 7 supports _Float128 and the f128 constant suffix for C, not for 
C++.  The header will need to do appropriate things for C++: either 
declare the feature not to be supported, or, if you want to be able to use 
the APIs for C++ (which seems sensible), map _Float128 to __float128 for 
C++ even for GCC 7 and later.
Gabriel F. T. Gomes May 11, 2017, 8:49 p.m. UTC | #3
On Tue, 9 May 2017 22:56:22 +0000
Joseph Myers <joseph@codesourcery.com> wrote:

> On Tue, 9 May 2017, Gabriel F. T. Gomes wrote:
>
> > --- /dev/null
> > +++ b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h  
> 
> GCC supports a range of multilib configurations with both BE and LE 
> libraries for powerpc64.
> 
> In such configurations, the same headers are shared between multilibs.  So 
> you can't have a separate version of an installed header for powerpc64le.  
> Instead, you need to have one header with appropriate preprocessor 
> conditionals that express that _Float128 is supported for powerpc64le, but 
> not for BE.  And it would go in sysdeps/powerpc so all powerpc 
> configurations get that same header installed.

OK.

> Or maybe nothing actually requires bits/floatn.h and bits/floatn-compat.h 
> to be separate and all the definitions should just go in bits/floatn.h 
> unless and until there are two architectures that need different versions 
> of one of the headers but the same version of the other.  That would avoid 
> various places needing to #include bits/floatn-compat.h, and avoid the 
> need to get includes in the correct order.

With bits/floatn.h moved from sysdeps/powerpc/powerpc64le to
sysdeps/powerpc (as explained above), merging bits/floatn-compat.h into
bits/floatn.h means that the workarounds for old compilers will be visible
in the headers for powerpc and powerpc64 installations.  That doesn't mean
that the workarounds will be defined (since they'll be inside #if
clauses).  Is that visibility a problem?

> > diff --git a/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h  
> 
> I think this file would better be in one of the patches actually adding 
> support on powerpc rather than in the present series, but I may as well 
> review the contents now.

Since I moved this change to a future patch.  I attached the file here in
case you want to comment at this time.
Joseph Myers May 11, 2017, 9:57 p.m. UTC | #4
On Thu, 11 May 2017, Gabriel F. T. Gomes wrote:

> > Or maybe nothing actually requires bits/floatn.h and bits/floatn-compat.h 
> > to be separate and all the definitions should just go in bits/floatn.h 
> > unless and until there are two architectures that need different versions 
> > of one of the headers but the same version of the other.  That would avoid 
> > various places needing to #include bits/floatn-compat.h, and avoid the 
> > need to get includes in the correct order.
> 
> With bits/floatn.h moved from sysdeps/powerpc/powerpc64le to
> sysdeps/powerpc (as explained above), merging bits/floatn-compat.h into
> bits/floatn.h means that the workarounds for old compilers will be visible
> in the headers for powerpc and powerpc64 installations.  That doesn't mean
> that the workarounds will be defined (since they'll be inside #if
> clauses).  Is that visibility a problem?

No, it's expected.

> #define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
> #include <bits/libc-header-start.h>

This shouldn't be necessary in bits/floatn.h, only in the including 
header.  (And I'd say that bits/floatn.h should have a multiple-inclusion 
guard.)

> /* Defined to concatenate the literal suffix to be used with _Float128
>    types, if __HAVE_FLOAT128 is 1. */
> #if __HAVE_FLOAT128
> # if !__GNUC_PREREQ (7, 0)
> /* The literal suffix (f128) exist for powerpc only since GCC 7.0.  */
> #  define __f128(x) x##q
> # else
> #  define __f128(x) x##f128
> # endif
> #endif

Needs to allow for C++ (given that you've defined __HAVE_FLOAT128 for C++, 
but C++ doesn't have the f128 suffix).

> /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
> #if __HAVE_FLOAT128
> # if !__GNUC_PREREQ (7, 0)
> /* Add a typedef for older GCC compilers which don't natively support
>    _Complex _Float128.  */
> typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__KC__)));
> #  define __CFLOAT128 __cfloat128
> # else
> #  define __CFLOAT128 _Complex _Float128
> # endif
> #endif

Likewise.

> /* The type _Float128 exist for powerpc only since GCC 7.0.  */
> # if !__GNUC_PREREQ (7, 0)
> typedef __float128 _Float128;
> # endif

Would need to do this for C++ for newer compilers as well.
diff mbox

Patch

diff --git a/bits/floatn-compat.h b/bits/floatn-compat.h
new file mode 100644
index 0000000..2fc7d35
--- /dev/null
+++ b/bits/floatn-compat.h
@@ -0,0 +1,20 @@ 
+/* Define _FloatN macros for ISO/IEC TS-18661-3 support, when needed.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Nothing to be done, here.  Each platform that provides _FloatN support
+   defines the required macros in sysdeps.  */
diff --git a/bits/floatn.h b/bits/floatn.h
new file mode 100644
index 0000000..94fc357
--- /dev/null
+++ b/bits/floatn.h
@@ -0,0 +1,30 @@ 
+/* Macros to control TS 18661-3 glibc features.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Defined to 1 if the current compiler invocation provides a
+   floating-point type with the IEEE 754 binary128 format, and this glibc
+   includes corresponding *f128 interfaces for it.  */
+#define __HAVE_FLOAT128 0
+
+/* Defined to 1 if __HAVE_FLOAT128 is 1 and the type is ABI-distinct
+   from the default float, double and long double types in this glibc.  */
+#define __HAVE_DISTINCT_FLOAT128 0
+
+/* Defined for GCC versions which support the __float128 type, but not
+   _Complex __float128.  This resolves to a complex binary128 type.  */
+#undef __CFLOAT128
diff --git a/bits/huge_val_flt128.h b/bits/huge_val_flt128.h
new file mode 100644
index 0000000..63c258e
--- /dev/null
+++ b/bits/huge_val_flt128.h
@@ -0,0 +1,23 @@ 
+/* Default `HUGE_VAL_F128' constant.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_H
+# error "Never use <bits/huge_val_flt128.h> directly; include <math.h> instead."
+#endif
+
+#define HUGE_VAL_F128 (__builtin_huge_valf128 ())
diff --git a/bits/libm-simd-decl-stubs.h b/bits/libm-simd-decl-stubs.h
index 7328eb2..6794b9f 100644
--- a/bits/libm-simd-decl-stubs.h
+++ b/bits/libm-simd-decl-stubs.h
@@ -36,24 +36,30 @@ 
 #define __DECL_SIMD_cos
 #define __DECL_SIMD_cosf
 #define __DECL_SIMD_cosl
+#define __DECL_SIMD_cosf128
 
 #define __DECL_SIMD_sin
 #define __DECL_SIMD_sinf
 #define __DECL_SIMD_sinl
+#define __DECL_SIMD_sinf128
 
 #define __DECL_SIMD_sincos
 #define __DECL_SIMD_sincosf
 #define __DECL_SIMD_sincosl
+#define __DECL_SIMD_sincosf128
 
 #define __DECL_SIMD_log
 #define __DECL_SIMD_logf
 #define __DECL_SIMD_logl
+#define __DECL_SIMD_logf128
 
 #define __DECL_SIMD_exp
 #define __DECL_SIMD_expf
 #define __DECL_SIMD_expl
+#define __DECL_SIMD_expf128
 
 #define __DECL_SIMD_pow
 #define __DECL_SIMD_powf
 #define __DECL_SIMD_powl
+#define __DECL_SIMD_powf128
 #endif
diff --git a/math/Makefile b/math/Makefile
index 634c619..621050a 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -29,7 +29,8 @@  headers		:= math.h bits/mathcalls.h bits/mathinline.h bits/huge_val.h \
 		   bits/math-finite.h bits/math-vector.h \
 		   bits/libm-simd-decl-stubs.h bits/iscanonical.h \
 		   bits/flt-eval-method.h bits/fp-fast.h bits/fp-logb.h \
-		   bits/long-double.h bits/mathcalls-helper-functions.h
+		   bits/long-double.h bits/mathcalls-helper-functions.h \
+		   bits/floatn.h bits/floatn-compat.h bits/huge_val_flt128.h
 
 # FPU support code.
 aux		:= setfpucw fpu_control
diff --git a/math/bits/cmathcalls.h b/math/bits/cmathcalls.h
index 6e13930..7f042db 100644
--- a/math/bits/cmathcalls.h
+++ b/math/bits/cmathcalls.h
@@ -44,7 +44,9 @@ 
 #error "Never use <bits/cmathcalls.h> directly; include <complex.h> instead."
 #endif
 
-#define _Mdouble_complex_ _Mdouble_ _Complex
+#ifndef _Mdouble_complex_
+# define _Mdouble_complex_ _Mdouble_ _Complex
+#endif
 
 
 /* Trigonometric functions.  */
diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h
index 0d341fb..745f121 100644
--- a/math/bits/mathcalls.h
+++ b/math/bits/mathcalls.h
@@ -115,7 +115,9 @@  __MATHCALL (exp10,, (_Mdouble_ __x));
 #endif
 #ifdef __USE_GNU
 /* Another name occasionally used.  */
+# ifndef __FLOATN_TYPE
 __MATHCALL (pow10,, (_Mdouble_ __x));
+# endif
 #endif
 
 #if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
@@ -172,14 +174,16 @@  __MATHCALLX (floor,, (_Mdouble_ __x), (__const__));
 __MATHCALL (fmod,, (_Mdouble_ __x, _Mdouble_ __y));
 
 #ifdef __USE_MISC
-# if (!defined __cplusplus \
-      || __cplusplus < 201103L /* isinf conflicts with C++11.  */ \
-      || __MATH_DECLARING_DOUBLE == 0) /* isinff or isinfl don't.  */
+# if ((!defined __cplusplus \
+       || __cplusplus < 201103L /* isinf conflicts with C++11.  */ \
+       || __MATH_DECLARING_DOUBLE == 0)) /* isinff or isinfl don't.  */ \
+      && !defined __FLOATN_TYPE
 /* Return 0 if VALUE is finite or NaN, +1 if it
    is +Infinity, -1 if it is -Infinity.  */
 __MATHDECL_1 (int,isinf,, (_Mdouble_ __value)) __attribute__ ((__const__));
 # endif
 
+# ifndef __FLOATN_TYPE
 /* Return nonzero if VALUE is finite and not NaN.  */
 __MATHDECL_1 (int,finite,, (_Mdouble_ __value)) __attribute__ ((__const__));
 
@@ -189,6 +193,8 @@  __MATHCALL (drem,, (_Mdouble_ __x, _Mdouble_ __y));
 
 /* Return the fractional part of X after dividing out `ilogb (X)'.  */
 __MATHCALL (significand,, (_Mdouble_ __x));
+# endif
+
 #endif /* Use misc.  */
 
 #ifdef __USE_ISOC99
@@ -203,9 +209,10 @@  __MATHCALLX (nan,, (const char *__tagb), (__const__));
 
 
 #if defined __USE_MISC || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
-# if (!defined __cplusplus \
-      || __cplusplus < 201103L /* isnan conflicts with C++11.  */ \
-      || __MATH_DECLARING_DOUBLE == 0) /* isnanf or isnanl don't.  */
+# if ((!defined __cplusplus \
+       || __cplusplus < 201103L /* isnan conflicts with C++11.  */ \
+       || __MATH_DECLARING_DOUBLE == 0)) /* isnanf or isnanl don't.  */ \
+      && !defined __FLOATN_TYPE
 /* Return nonzero if VALUE is not a number.  */
 __MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
 # endif
@@ -235,8 +242,10 @@  __MATHCALL (tgamma,, (_Mdouble_));
 #endif
 
 #if defined __USE_MISC || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
+# ifndef __FLOATN_TYPE
 /* Obsolete alias for `lgamma'.  */
 __MATHCALL (gamma,, (_Mdouble_));
+# endif
 #endif
 
 #ifdef __USE_MISC
@@ -254,11 +263,11 @@  __MATHCALL (rint,, (_Mdouble_ __x));
 
 /* Return X + epsilon if X < Y, X - epsilon if X > Y.  */
 __MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__));
-# if defined __USE_ISOC99 && !defined __LDBL_COMPAT
+# if defined __USE_ISOC99 && !defined __LDBL_COMPAT && !defined __FLOATN_TYPE
 __MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__));
 # endif
 
-#if __GLIBC_USE (IEC_60559_BFP_EXT)
+#if __GLIBC_USE (IEC_60559_BFP_EXT) || defined __FLOATN_TYPE
 /* Return X - epsilon.  */
 __MATHCALL (nextdown,, (_Mdouble_ __x));
 /* Return X + epsilon.  */
@@ -277,7 +286,7 @@  __MATHCALL (scalbn,, (_Mdouble_ __x, int __n));
 __MATHDECL (int,ilogb,, (_Mdouble_ __x));
 #endif
 
-#if __GLIBC_USE (IEC_60559_BFP_EXT)
+#if __GLIBC_USE (IEC_60559_BFP_EXT) || defined __FLOATN_TYPE
 /* Like ilogb, but returning long int.  */
 __MATHDECL (long int, llogb,, (_Mdouble_ __x));
 #endif
@@ -332,7 +341,7 @@  __MATHCALLX (fmin,, (_Mdouble_ __x, _Mdouble_ __y), (__const__));
 __MATHCALL (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z));
 #endif /* Use ISO C99.  */
 
-#if __GLIBC_USE (IEC_60559_BFP_EXT)
+#if __GLIBC_USE (IEC_60559_BFP_EXT) || defined __FLOATN_TYPE
 /* Round X to nearest integer value, rounding halfway cases to even.  */
 __MATHCALLX (roundeven,, (_Mdouble_ __x), (__const__));
 
@@ -385,9 +394,10 @@  __MATHDECL_1 (int, setpayload,, (_Mdouble_ *__x, _Mdouble_ __payload));
 __MATHDECL_1 (int, setpayloadsig,, (_Mdouble_ *__x, _Mdouble_ __payload));
 #endif
 
-#if defined __USE_MISC || (defined __USE_XOPEN_EXTENDED \
-			   && __MATH_DECLARING_DOUBLE	\
-			   && !defined __USE_XOPEN2K8)
+#if (defined __USE_MISC || (defined __USE_XOPEN_EXTENDED \
+			    && __MATH_DECLARING_DOUBLE	  \
+			    && !defined __USE_XOPEN2K8))  \
+     && !defined __FLOATN_TYPE
 /* Return X times (2 to the Nth power).  */
 __MATHCALL (scalb,, (_Mdouble_ __x, _Mdouble_ __n));
 #endif
diff --git a/math/complex.h b/math/complex.h
index 59ce30e..9a730d3 100644
--- a/math/complex.h
+++ b/math/complex.h
@@ -22,11 +22,15 @@ 
 #ifndef _COMPLEX_H
 #define _COMPLEX_H	1
 
-#include <features.h>
+#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
+#include <bits/libc-header-start.h>
 
 /* Get general and ISO C99 specific information.  */
 #include <bits/mathdef.h>
 
+/* Gather machine-dependent _FloatN type support.  */
+#include <bits/floatn.h>
+
 __BEGIN_DECLS
 
 /* We might need to add support for more compilers here.  But since ISO
@@ -55,6 +59,10 @@  __BEGIN_DECLS
 # define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y))
 #endif
 
+#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+# define CMPLXF128(x, y) __builtin_complex ((_Float128) (x), (_Float128) (y))
+#endif
+
 /* The file <bits/cmathcalls.h> contains the prototypes for all the
    actual math functions.  These macros are used for those prototypes,
    so we can easily declare each function as both `name' and `__name',
@@ -84,6 +92,23 @@  __BEGIN_DECLS
 #undef	_Mdouble_
 #undef	__MATH_PRECNAME
 
+#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+# ifndef _Mfloat128_
+#  define _Mfloat128_		_Float128
+# endif
+/* GCC < 7 requires extra convincing to expose a complex float128 type.  */
+# ifdef __CFLOAT128
+#  undef _Mdouble_complex_
+#  define _Mdouble_complex_	__CFLOAT128
+# endif
+# define _Mdouble_		_Mfloat128_
+# define __MATH_PRECNAME(name)	name##f128
+# include <bits/cmathcalls.h>
+# undef _Mdouble_
+# undef __MATH_PRECNAME
+# undef _Mdouble_complex_
+#endif
+
 /* And the long double versions.  It is non-critical to define them
    here unconditionally since `long double' is required in ISO C99.  */
 #if !(defined __NO_LONG_DOUBLE_MATH && defined _LIBC)	\
diff --git a/math/math.h b/math/math.h
index cfaed0e..60a3bda 100644
--- a/math/math.h
+++ b/math/math.h
@@ -34,9 +34,17 @@  __BEGIN_DECLS
 /* Get machine-dependent vector math functions declarations.  */
 #include <bits/math-vector.h>
 
+/* Gather machine dependent type support.  */
+#include <bits/floatn.h>
+
 /* Get machine-dependent HUGE_VAL value (returned on overflow).
    On all IEEE754 machines, this is +Infinity.  */
 #include <bits/huge_val.h>
+
+#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+# include <bits/huge_val_flt128.h>
+#endif
+
 #ifdef __USE_ISOC99
 # include <bits/huge_valf.h>
 # include <bits/huge_vall.h>
@@ -206,6 +214,7 @@  enum
   extern type __MATH_PRECNAME(function,suffix) args __THROW
 
 #define _Mdouble_		double
+#undef __FLOATN_TYPE
 #define __MATH_PRECNAME(name,r)	__CONCAT(name,r)
 #define __MATH_DECLARING_DOUBLE  1
 #include <bits/mathcalls-helper-functions.h>
@@ -223,6 +232,7 @@  enum
 # ifndef _Mfloat_
 #  define _Mfloat_		float
 # endif
+# undef __FLOATN_TYPE
 # define _Mdouble_		_Mfloat_
 # define __MATH_PRECNAME(name,r) name##f##r
 # define __MATH_DECLARING_DOUBLE  0
@@ -266,6 +276,7 @@  extern long double __REDIRECT_NTH (nexttowardl,
 #  ifndef _Mlong_double_
 #   define _Mlong_double_	long double
 #  endif
+#  undef __FLOATN_TYPE
 #  define _Mdouble_		_Mlong_double_
 #  define __MATH_PRECNAME(name,r) name##l##r
 #  define __MATH_DECLARING_DOUBLE  0
@@ -279,6 +290,28 @@  extern long double __REDIRECT_NTH (nexttowardl,
 # endif /* !(__NO_LONG_DOUBLE_MATH && _LIBC) || __LDBL_COMPAT */
 
 #endif	/* Use ISO C99.  */
+
+/* Include the file of declarations again, this time using `_Float128'
+   instead of `double' and appending f128 to each function name.  */
+
+#if __HAVE_DISTINCT_FLOAT128
+# ifndef _Mfloat128_
+#  define _Mfloat128_		_Float128
+# endif
+# define __FLOATN_TYPE		1
+# define _Mdouble_		_Mfloat128_
+# define __MATH_PRECNAME(name,r) name##f128##r
+# define __MATH_DECLARING_DOUBLE  0
+# include <bits/mathcalls-helper-functions.h>
+# if __GLIBC_USE (IEC_60559_TYPES_EXT)
+#  include <bits/mathcalls.h>
+# endif
+# undef __FLOATN_TYPE
+# undef _Mdouble_
+# undef __MATH_PRECNAME
+# undef __MATH_DECLARING_DOUBLE
+#endif /* __HAVE_DISTINCT_FLOAT128.  */
+
 #undef	__MATHDECL_1
 #undef	__MATHDECL
 #undef	__MATHCALL
@@ -377,7 +410,13 @@  enum
 # endif
 
 /* Return nonzero value if X is positive or negative infinity.  */
-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
+# if __HAVE_DISTINCT_FLOAT128 && !__GNUC_PREREQ (7,0) \
+     && !defined __SUPPORT_SNAN__
+   /* __builtin_isinf_sign is broken for float128 only before GCC 7.0.  */
+#  define isinf(x) \
+    (__builtin_types_compatible_p (typeof (x), _Float128) \
+     ? __isinff128 (x) : __builtin_isinf_sign (x))
+# elif __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
 #  define isinf(x) __builtin_isinf_sign (x)
 # else
 #  define isinf(x) __MATH_TG ((x), __isinf, (x))
@@ -529,6 +568,26 @@  extern int matherr (struct exception *__exc);
 # define M_SQRT1_2l	0.707106781186547524400844362104849039L /* 1/sqrt(2) */
 #endif
 
+#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT) && defined __USE_GNU
+# if defined __GNUC__ && !__GNUC_PREREQ (7,0)
+#  define __f128(x) x ## q
+# else
+#  define __f128(x) x ## f128
+# endif
+# define M_Ef128	__f128 (2.718281828459045235360287471352662498) /* e */
+# define M_LOG2Ef128	__f128 (1.442695040888963407359924681001892137) /* log_2 e */
+# define M_LOG10Ef128	__f128 (0.434294481903251827651128918916605082) /* log_10 e */
+# define M_LN2f128	__f128 (0.693147180559945309417232121458176568) /* log_e 2 */
+# define M_LN10f128	__f128 (2.302585092994045684017991454684364208) /* log_e 10 */
+# define M_PIf128	__f128 (3.141592653589793238462643383279502884) /* pi */
+# define M_PI_2f128	__f128 (1.570796326794896619231321691639751442) /* pi/2 */
+# define M_PI_4f128	__f128 (0.785398163397448309615660845819875721) /* pi/4 */
+# define M_1_PIf128	__f128 (0.318309886183790671537767526745028724) /* 1/pi */
+# define M_2_PIf128	__f128 (0.636619772367581343075535053490057448) /* 2/pi */
+# define M_2_SQRTPIf128	__f128 (1.128379167095512573896158903121545172) /* 2/sqrt(pi) */
+# define M_SQRT2f128	__f128 (1.414213562373095048801688724209698079) /* sqrt(2) */
+# define M_SQRT1_2f128	__f128 (0.707106781186547524400844362104849039) /* 1/sqrt(2) */
+#endif
 
 /* When compiling in strict ISO C compatible mode we must not use the
    inline functions since they, among other things, do not set the
diff --git a/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h
new file mode 100644
index 0000000..7a711a8
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/bits/floatn-compat.h
@@ -0,0 +1,57 @@ 
+/* Define _FloatN macros for ISO/IEC TS-18661-3 support for powerpc64le.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if __HAVE_FLOAT128
+
+/* The type _Float128, as well as the literal suffix (F128), exist for powerpc
+   only since GCC 7.0.  */
+# if !__GNUC_PREREQ (7, 0)
+#  define __L(x) x##Q
+typedef __float128 _Float128;
+# else
+#  define __L(x) x##F128
+# endif
+
+/* Add a typedef for older GCC compilers which don't natively support
+   _Complex _Float128.  */
+# if !__GNUC_PREREQ (7, 0) && !defined __CFLOAT128
+typedef _Complex float __cfloat128 __attribute__ ((mode (KC)));
+#  define __CFLOAT128 __cfloat128
+# endif
+
+/* Builtin __builtin_huge_valf128 doesn't exist before GCC 7.0.  */
+# if !__GNUC_PREREQ (7, 0)
+#  define __builtin_huge_valf128() ((_Float128) __builtin_huge_val ())
+# endif
+
+/* The following builtins (suffixed with 'q') are available in GCC >= 6.2,
+   which is the minimum version required for float128 support on powerpc64le.
+   Since GCC 7.0 the builtins suffixed with f128 are also available, then
+   there is no need to redefined them.  */
+# if !__GNUC_PREREQ (7, 0)
+#  define __builtin_copysignf128 __builtin_copysignq
+#  define __builtin_fabsf128 __builtin_fabsq
+#  define __builtin_inff128 __builtin_infq
+#  define __builtin_nanf128 __builtin_nanq
+# endif
+
+/* __builtin_signbit is type generic in GCC 6.2, which is the minimum
+   version required for float128 support on powerpc64le.  */
+# define __builtin_signbitf128 __builtin_signbit
+
+#endif