about summary refs log tree commit diff
path: root/math/tgmath.h
diff options
context:
space:
mode:
Diffstat (limited to 'math/tgmath.h')
-rw-r--r--math/tgmath.h83
1 files changed, 57 insertions, 26 deletions
diff --git a/math/tgmath.h b/math/tgmath.h
index fc2fdcab37..ccc304ca62 100644
--- a/math/tgmath.h
+++ b/math/tgmath.h
@@ -36,12 +36,31 @@
 
 #if __GNUC_PREREQ (2, 7)
 
+/* This is ugly but unless gcc gets appropriate builtins we have to do
+   something like this.  Don't ask how it works.  */
+
+/* 1 if 'type' is a floating type, 0 if 'type' is an integer type.
+   Allows for _Bool.  Expands to an integer constant expression.  */
+#define __floating_type(type) (((type) 0.25) && ((type) 0.25 - 1))
+
+/* The tgmath real type for T, where E is 0 if T is an integer type and
+   1 for a floating type.  */
+#define __tgmath_real_type_sub(T, E) \
+  __typeof__(*(0 ? (__typeof__(0 ? (double *)0 : (void *)(E)))0		      \
+		 : (__typeof__(0 ? (T *)0 : (void *)(!(E))))0))
+
+/* The tgmath real type of EXPR.  */
+#define __tgmath_real_type(expr) \
+  __tgmath_real_type_sub(__typeof__(expr), __floating_type(__typeof__(expr)))
+
+
 /* 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__ ({ __typeof__ (Val) __tgmres;			      \
-		       if (sizeof (Val) == sizeof (double))		      \
+     (__extension__ ({ __tgmath_real_type (Val) __tgmres;		      \
+		       if (sizeof (Val) == sizeof (double)		      \
+			   || __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val);				      \
 		       else if (sizeof (Val) == sizeof (float))		      \
 			 __tgmres = Fct##f (Val);			      \
@@ -50,8 +69,9 @@
 		       __tgmres; }))
 
 # define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \
-     (__extension__ ({ __typeof__ (Val1) __tgmres;			      \
-		       if (sizeof (Val1) == sizeof (double))		      \
+     (__extension__ ({ __tgmath_real_type (Val1) __tgmres;		      \
+		       if (sizeof (Val1) == sizeof (double)		      \
+			   || __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val1, Val2);			      \
 		       else if (sizeof (Val1) == sizeof (float))	      \
 			 __tgmres = Fct##f (Val1, Val2);		      \
@@ -60,38 +80,44 @@
 		       __tgmres; }))
 
 # define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
-     (__extension__ ({ __typeof__ ((Val1) + (Val2)) __tgmres;		      \
-		       if (sizeof (Val1) > sizeof (double)		      \
-			   || sizeof (Val2) > sizeof (double))		      \
+     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;	      \
+		       if ((sizeof (Val1) > sizeof (double)		      \
+			    || sizeof (Val2) > sizeof (double))		      \
+			   && __builtin_classify_type (Val) == 8)	      \
 			 __tgmres = Fct##l (Val1, Val2);		      \
 		       else if (sizeof (Val1) == sizeof (double)	      \
-				|| sizeof (Val2) == sizeof (double))	      \
+				|| sizeof (Val2) == sizeof (double)	      \
+				|| __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val1, Val2);			      \
 		       else						      \
 			 __tgmres = Fct (Val1, Val2);			      \
 		       __tgmres; }))
 
 # define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
-     (__extension__ ({ __typeof__ ((Val1) + (Val2)) __tgmres;		      \
-		       if (sizeof (Val1) > sizeof (double)		      \
-			   || sizeof (Val2) > sizeof (double))		      \
+     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;	      \
+		       if ((sizeof (Val1) > sizeof (double)		      \
+			    || sizeof (Val2) > sizeof (double))		      \
+			   && __builtin_classify_type (Val) == 8)	      \
 			 __tgmres = Fct##l (Val1, Val2, Val3);		      \
 		       else if (sizeof (Val1) == sizeof (double)	      \
-				|| sizeof (Val2) == sizeof (double))	      \
+				|| sizeof (Val2) == sizeof (double)	      \
+				|| __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val1, Val2, Val3);		      \
 		       else						      \
 			 __tgmres = Fct (Val1, Val2, Val3);		      \
 		       __tgmres; }))
 
 # define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
-     (__extension__ ({ __typeof__ ((Val1) + (Val2) + (Val3)) __tgmres;	      \
-		       if (sizeof (Val1) > sizeof (double)		      \
-			   || sizeof (Val2) > sizeof (double)		      \
-			   || sizeof (Val3) > sizeof (double))		      \
+     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2) + (Val3)) __tgmres;\
+		       if ((sizeof (Val1) > sizeof (double)		      \
+			    || sizeof (Val2) > sizeof (double)		      \
+			    || sizeof (Val3) > sizeof (double))		      \
+			   && __builtin_classify_type (Val) == 8)	      \
 			 __tgmres = Fct##l (Val1, Val2, Val3);		      \
 		       else if (sizeof (Val1) == sizeof (double)	      \
 				|| sizeof (Val2) == sizeof (double)	      \
-				|| sizeof (Val3) == sizeof (double))	      \
+				|| sizeof (Val3) == sizeof (double)	      \
+				|| __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val1, Val2, Val3);		      \
 		       else						      \
 			 __tgmres = Fct (Val1, Val2, Val3);		      \
@@ -100,15 +126,17 @@
 /* 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__ ({ __typeof__ (Val) __tgmres;			      \
-		       if (sizeof (__real__ (Val)) > sizeof (double))	      \
+     (__extension__ ({ __tgmath_real_type (Val) __tgmres;		      \
+		       if (sizeof (__real__ (Val)) > sizeof (double)	      \
+			   && __builtin_classify_type (Val) == 8)	      \
 			 {						      \
 			   if (sizeof (__real__ (Val)) == sizeof (Val))	      \
 			     __tgmres = Fct##l (Val);			      \
 			   else						      \
 			     __tgmres = Cfct##l (Val);			      \
 			 }						      \
-		       else if (sizeof (__real__ (Val)) == sizeof (double))   \
+		       else if (sizeof (__real__ (Val)) == sizeof (double)    \
+				|| __builtin_classify_type (Val) != 8)	      \
 			 {						      \
 			   if (sizeof (__real__ (Val)) == sizeof (Val))	      \
 			     __tgmres = Fct (Val);			      \
@@ -127,8 +155,9 @@
 /* XXX This definition has to be changed as soon as the compiler understands
    the imaginary keyword.  */
 # define __TGMATH_UNARY_IMAG_ONLY(Val, Fct) \
-     (__extension__ ({ __typeof__ (Val) __tgmres;			      \
-		       if (sizeof (Val) == sizeof (__complex__ double))	      \
+     (__extension__ ({ __tgmath_real_type (Val) __tgmres;		      \
+		       if (sizeof (Val) == sizeof (__complex__ double)	      \
+			   || __builtin_classify_type (Val) != 8)	      \
 			 __tgmres = Fct (Val);				      \
 		       else if (sizeof (Val) == sizeof (__complex__ float))   \
 			 __tgmres = Fct##f (Val);			      \
@@ -139,9 +168,10 @@
 /* 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__ ({ __typeof__ ((Val1) + (Val2)) __tgmres;		      \
-		       if (sizeof (__real__ (Val1)) > sizeof (double)	      \
-			   || sizeof (__real__ (Val2)) > sizeof (double))     \
+     (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres;	      \
+		       if ((sizeof (__real__ (Val1)) > sizeof (double)	      \
+			    || sizeof (__real__ (Val2)) > sizeof (double))    \
+			   && __builtin_classify_type (Val) == 8)	      \
 			 {						      \
 			   if (sizeof (__real__ (Val1)) == sizeof (Val1)      \
 			       && sizeof (__real__ (Val2)) == sizeof (Val2))  \
@@ -150,7 +180,8 @@
 			     __tgmres = Cfct##l (Val1, Val2);		      \
 			 }						      \
 		       else if (sizeof (__real__ (Val1)) == sizeof (double)   \
-				|| sizeof (__real__ (Val2)) == sizeof(double))\
+				|| sizeof (__real__ (Val2)) == sizeof(double) \
+				|| __builtin_classify_type (Val) != 8)	      \
 			 {						      \
 			   if (sizeof (__real__ (Val1)) == sizeof (Val1)      \
 			       && sizeof (__real__ (Val2)) == sizeof (Val2))  \