From 49154ceabd6b421c3a004ce1bcfaabfbefa1edaa Mon Sep 17 00:00:00 2001
From: "Paul E. Murphy" <murphyp@linux.vnet.ibm.com>
Date: Fri, 3 Jun 2016 15:44:05 -0500
Subject: [PATCH 2/2] [RFC] Rewrite tgmath.h helper macros

To support more types, these need to be extensible to additional
FP types.  This is ugly.  This assumes __builtin_types_compatible_p()
exists on much older GCC variants.
---
 math/tgmath.h | 240 +++++++++++++++++-----------------------------------------
 1 file changed, 71 insertions(+), 169 deletions(-)

diff --git a/math/tgmath.h b/math/tgmath.h
index ea2b611..f137326 100644
--- a/math/tgmath.h
+++ b/math/tgmath.h
@@ -66,179 +66,81 @@
   __tgmath_real_type_sub (__typeof__ ((__typeof__ (expr)) 0),		      \
 			  __floating_type (__typeof__ (expr)))
 
+/* Type promotion macros.  */
+# define __TGT1(v) __tgmath_real_type(v)
+# define __TGT2(v1, v2) __typeof ((__TGT1 (v1)) 0 + (__TGT1 (v2)) 0)
+# define __TGT3(v1, v2, v3) __typeof ((__TGT2 (v1, v2)) 0 + (__TGT1 (v3)) 0)
+
+# define __TGCMPLXTYPE(t) __typeof ((__TGT1 (t)) 0 + _Complex_I)
+# define __TGREALTYPE(t) __typeof (__real__ (__TGT1 (t)) 0)
+# define __TGISCMPLX(v) (sizeof (v) != sizeof (__real__ (v)))
+
+# define __TGTTEMP(TYPE,FUNC,type,...) \
+  else if (__builtin_types_compatible_p (type, TYPE)) \
+    _ret = FUNC (__VA_ARGS__);
+
+# define __TG_ELIF_TYPE(M, FUNC, type, ...) \
+	__TGTTEMP (M long double, __tgml (FUNC), type, __VA_ARGS__)	\
+	__TGTTEMP (M double, FUNC, type, __VA_ARGS__) 			\
+	__TGTTEMP (M float, FUNC ## f, type, __VA_ARGS__)
+
+# define __TGTEMP_BASE(M, it, rt, f, ...) \
+  ({								    \
+    __typeof__ (rt) _ret = 0;					    \
+    if(0)							    \
+      {}							    \
+    __TG_ELIF_TYPE (M, f, it, __VA_ARGS__)			    \
+    else							    \
+      _ret = f (__VA_ARGS__);					    \
+    _ret;							    \
+  })
+
+# define __TGTEMP_REAL(it, rt, f, ...) \
+  __TGTEMP_BASE (, it, rt, f, __VA_ARGS__)
+
+# define __TGTEMP_REAL_CMPLX(it, rt, f, cf, ...) \
+  ({									\
+    __typeof__ (rt) _ret = 0;						\
+    if (__TGISCMPLX ((it) 0))						\
+      _ret = __TGTEMP_BASE (_Complex, it, rt, cf, __VA_ARGS__);		\
+    else								\
+      _ret = __TGTEMP_BASE (, it, rt, f, __VA_ARGS__);			\
+    _ret;								\
+  })
 
 /* We have two kinds of generic macros: to support functions which are
    only defined on real valued parameters and those which are defined
    for complex functions as well.  */
-# define __TGMATH_UNARY_REAL_ONLY(Val, Fct) \
-     (__extension__ ((sizeof (Val) == sizeof (double)			      \
-		      || __builtin_classify_type (Val) != 8)		      \
-		     ? (__tgmath_real_type (Val)) Fct (Val)		      \
-		     : (sizeof (Val) == sizeof (float))			      \
-		     ? (__tgmath_real_type (Val)) Fct##f (Val)		      \
-		     : (__tgmath_real_type (Val)) __tgml(Fct) (Val)))
-
-# define __TGMATH_UNARY_REAL_RET_ONLY(Val, RetType, Fct) \
-     (__extension__ ((sizeof (Val) == sizeof (double)			      \
-		      || __builtin_classify_type (Val) != 8)		      \
-		     ? (RetType) Fct (Val)				      \
-		     : (sizeof (Val) == sizeof (float))			      \
-		     ? (RetType) Fct##f (Val)				      \
-		     : (RetType) __tgml(Fct) (Val)))
-
-# define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \
-     (__extension__ ((sizeof (Val1) == sizeof (double)			      \
-		      || __builtin_classify_type (Val1) != 8)		      \
-		     ? (__tgmath_real_type (Val1)) Fct (Val1, Val2)	      \
-		     : (sizeof (Val1) == sizeof (float))		      \
-		     ? (__tgmath_real_type (Val1)) Fct##f (Val1, Val2)	      \
-		     : (__tgmath_real_type (Val1)) __tgml(Fct) (Val1, Val2)))
-
-# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
-     (__extension__ (((sizeof (Val1) > sizeof (double)			      \
-		       || sizeof (Val2) > sizeof (double))		      \
-		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       __tgml(Fct) (Val1, Val2)				      \
-		     : (sizeof (Val1) == sizeof (double)		      \
-			|| sizeof (Val2) == sizeof (double)		      \
-			|| __builtin_classify_type (Val1) != 8		      \
-			|| __builtin_classify_type (Val2) != 8)		      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       Fct (Val1, Val2)					      \
-		     : (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       Fct##f (Val1, Val2)))
-
-# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
-     (__extension__ (((sizeof (Val1) > sizeof (double)			      \
-		       || sizeof (Val2) > sizeof (double))		      \
-		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       __tgml(Fct) (Val1, Val2, Val3)			      \
-		     : (sizeof (Val1) == sizeof (double)		      \
-			|| sizeof (Val2) == sizeof (double)		      \
-			|| __builtin_classify_type (Val1) != 8		      \
-			|| __builtin_classify_type (Val2) != 8)		      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       Fct (Val1, Val2, Val3)				      \
-		     : (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-		       Fct##f (Val1, Val2, Val3)))
-
-# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
-     (__extension__ (((sizeof (Val1) > sizeof (double)			      \
-		       || sizeof (Val2) > sizeof (double)		      \
-		       || sizeof (Val3) > sizeof (double))		      \
-		      && __builtin_classify_type ((Val1) + (Val2) + (Val3))   \
-			 == 8)						      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0	      \
-				   + (__tgmath_real_type (Val3)) 0))	      \
-		       __tgml(Fct) (Val1, Val2, Val3)			      \
-		     : (sizeof (Val1) == sizeof (double)		      \
-			|| sizeof (Val2) == sizeof (double)		      \
-			|| sizeof (Val3) == sizeof (double)		      \
-			|| __builtin_classify_type (Val1) != 8		      \
-			|| __builtin_classify_type (Val2) != 8		      \
-			|| __builtin_classify_type (Val3) != 8)		      \
-		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0	      \
-				   + (__tgmath_real_type (Val3)) 0))	      \
-		       Fct (Val1, Val2, Val3)				      \
-		     : (__typeof ((__tgmath_real_type (Val1)) 0		      \
-				   + (__tgmath_real_type (Val2)) 0	      \
-				   + (__tgmath_real_type (Val3)) 0))	      \
-		       Fct##f (Val1, Val2, Val3)))
-
-/* XXX This definition has to be changed as soon as the compiler understands
-   the imaginary keyword.  */
-# define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \
-     (__extension__ ((sizeof (__real__ (Val)) == sizeof (double)	      \
-		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
-		     ? ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__tgmath_real_type (Val)) Fct (Val)		      \
-			: (__tgmath_real_type (Val)) Cfct (Val))	      \
-		     : (sizeof (__real__ (Val)) == sizeof (float))	      \
-		     ? ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__tgmath_real_type (Val)) Fct##f (Val)	      \
-			: (__tgmath_real_type (Val)) Cfct##f (Val))	      \
-		     : ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__tgmath_real_type (Val)) __tgml(Fct) (Val)	      \
-			: (__tgmath_real_type (Val)) __tgml(Cfct) (Val))))
-
-# define __TGMATH_UNARY_IMAG(Val, Cfct) \
-     (__extension__ ((sizeof (__real__ (Val)) == sizeof (double)	      \
-		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
-		     ? (__typeof__ ((__tgmath_real_type (Val)) 0	      \
-				    + _Complex_I)) Cfct (Val)		      \
-		     : (sizeof (__real__ (Val)) == sizeof (float))	      \
-		     ? (__typeof__ ((__tgmath_real_type (Val)) 0	      \
-				    + _Complex_I)) Cfct##f (Val)	      \
-		     : (__typeof__ ((__tgmath_real_type (Val)) 0	      \
-				    + _Complex_I)) __tgml(Cfct) (Val)))
-
-/* XXX This definition has to be changed as soon as the compiler understands
-   the imaginary keyword.  */
-# define __TGMATH_UNARY_REAL_IMAG_RET_REAL(Val, Fct, Cfct) \
-     (__extension__ ((sizeof (__real__ (Val)) == sizeof (double)	      \
-		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
-		     ? ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  Fct (Val)					      \
-			: (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  Cfct (Val))					      \
-		     : (sizeof (__real__ (Val)) == sizeof (float))	      \
-		     ? ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  Fct##f (Val)					      \
-			: (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  Cfct##f (Val))				      \
-		     : ((sizeof (__real__ (Val)) == sizeof (Val))	      \
-			? (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  __tgml(Fct) (Val)				      \
-			: (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))\
-			  __tgml(Cfct) (Val))))
-
-/* XXX This definition has to be changed as soon as the compiler understands
-   the imaginary keyword.  */
-# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
-     (__extension__ (((sizeof (__real__ (Val1)) > sizeof (double)	      \
-		       || sizeof (__real__ (Val2)) > sizeof (double))	      \
-		      && __builtin_classify_type (__real__ (Val1)	      \
-						  + __real__ (Val2)) == 8)    \
-		     ? ((sizeof (__real__ (Val1)) == sizeof (Val1)	      \
-			 && sizeof (__real__ (Val2)) == sizeof (Val2))	      \
-			? (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  __tgml(Fct) (Val1, Val2)			      \
-			: (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  __tgml(Cfct) (Val1, Val2))			      \
-		     : (sizeof (__real__ (Val1)) == sizeof (double)	      \
-			|| sizeof (__real__ (Val2)) == sizeof (double)	      \
-			|| __builtin_classify_type (__real__ (Val1)) != 8     \
-			|| __builtin_classify_type (__real__ (Val2)) != 8)    \
-		     ? ((sizeof (__real__ (Val1)) == sizeof (Val1)	      \
-			 && sizeof (__real__ (Val2)) == sizeof (Val2))	      \
-			? (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  Fct (Val1, Val2)				      \
-			: (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  Cfct (Val1, Val2))				      \
-		     : ((sizeof (__real__ (Val1)) == sizeof (Val1)	      \
-			 && sizeof (__real__ (Val2)) == sizeof (Val2))	      \
-			? (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  Fct##f (Val1, Val2)				      \
-			: (__typeof ((__tgmath_real_type (Val1)) 0	      \
-				   + (__tgmath_real_type (Val2)) 0))	      \
-			  Cfct##f (Val1, Val2))))
+# define __TGMATH_UNARY_REAL_ONLY(V,Fct) \
+	__TGTEMP_REAL (__TGT1 (V), __TGT1 (V), Fct, V)
+
+# define __TGMATH_UNARY_REAL_RET_ONLY(V, RetType, Fct) \
+	__TGTEMP_REAL (__TGT1 (V), RetType, Fct, V)
+
+# define __TGMATH_BINARY_FIRST_REAL_ONLY(V1, V2, Fct) \
+	__TGTEMP_REAL (__TGT1 (V1), __TGT1 (V1), Fct, V1, V2)
+
+# define __TGMATH_BINARY_REAL_ONLY(V1, V2, Fct) \
+	__TGTEMP_REAL (__TGT2 (V1, V2), __TGT2 (V1, V2), Fct, V1, V2)
+
+# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(V1, V2, V3, Fct) \
+	__TGTEMP_REAL (__TGT2 (V1, V2), __TGT2 (V1, V2), Fct, V1, V2, V3)
+
+# define __TGMATH_TERNARY_REAL_ONLY(V1, V2, V3, F) \
+	__TGTEMP_REAL (__TGT3 (V1, V2, V3), __TGT3 (V1, V2, V3), F, V1, V2, V3)
+
+# define __TGMATH_UNARY_REAL_IMAG(V, Fct, Cfct) \
+	__TGTEMP_REAL_CMPLX (__TGT1 (V), __TGT1 (V), Fct, Cfct, V)
+
+# define __TGMATH_UNARY_IMAG(V, Cfct) \
+	__TGTEMP_REAL_CMPLX (__TGT1 (V), __TGCMPLXTYPE (V), Cfct, Cfct, V)
+
+# define __TGMATH_UNARY_REAL_IMAG_RET_REAL(V, Fct, Cfct) \
+	__TGTEMP_REAL_CMPLX (__TGT1 (V), __TGREALTYPE (V), Fct, Cfct, V)
+
+# define __TGMATH_BINARY_REAL_IMAG(V1, V2, F, CF) \
+	__TGTEMP_REAL_CMPLX (__TGT2 (V1, V2), __TGT2 (V1, V2), F, CF, V1, V2)
+
 #else
 # error "Unsupported compiler; you cannot use <tgmath.h>"
 #endif
-- 
2.4.11

