This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] tgmath.h and math/Makefile refactor


These are two separate smaller patches, inching towards the goal of
supporting more FP types in libm.

I spent some time trying to figure out tgmath.h, and how it might look
with support for arbitrary types.  It assumes __builtin_types_compatible_p
and Statement Expr's are supported by GCC (I'm not sure when these were
added).  These macros might make a good basis for supporting the
classification macros in math.h.

The potential Makefile changes by comparison are rather self-explanatory.
>From aa47b73325e4affd90428e8a8f8af91b684fea5b Mon Sep 17 00:00:00 2001
From: "Paul E. Murphy" <murphyp@linux.vnet.ibm.com>
Date: Fri, 3 Jun 2016 15:44:12 -0500
Subject: [PATCH 1/2] [RFC] Refactor math Makefile

In order to support more types, the Makefile needs a few bits
shuffled in order to support them.

I've separated the functions which are defined by TS 18661-3
into the variable ts-18661-calls, and the rest into gnu-libm-calls
from libm-calls.

I've also place a capital F as a placeholder for the type suffix
on each type.  This removes the need to demangle _rF to F_r when
applying them.

Finally, I've added the hooks to demonstrate what adding float128
will look like.  They are unbuildable, and turned off by default.

This implicitly describes all functions which must be defined when
adding support for a new type.
---
 math/Makefile | 193 ++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 127 insertions(+), 66 deletions(-)

diff --git a/math/Makefile b/math/Makefile
index f0265bb..7e7f1be 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -37,55 +37,117 @@ aux		:= setfpucw fpu_control
 extra-libs	:= libm
 extra-libs-others = $(extra-libs)
 
+# Function outlined by TS 18661-3, and GNU derivatives.
+ts-18661-calls = \
+	e_acosF e_acoshF e_asinF e_atan2F e_atanhF e_coshF e_expF e_fmodF \
+	e_hypotF e_lgammaF_r e_logF e_log10F e_powF			  \
+	e_remainderF e_sinhF e_sqrtF e_gammaF_r				  \
+	e_ilogbF							  \
+	k_cosF k_sinF k_tanF s_asinhF s_atanF s_cbrtF			  \
+	s_ceilF s_cosF s_erfF s_expm1F s_fabsF				  \
+	s_floorF s_log1pF w_log1pF s_logbF				  \
+	s_nextafterF s_rintF s_scalblnF w_scalblnF			  \
+	s_sinF s_tanF s_tanhF w_acosF w_acoshF w_asinF			  \
+	w_atan2F w_atanhF w_coshF w_expF w_exp2F w_exp10F w_fmodF	  \
+	w_tgammaF w_hypotF w_lgammaF w_lgammaF_r			  \
+	w_logF w_log10F w_powF w_remainderF w_sinhF w_sqrtF		  \
+	w_ilogbF							  \
+	s_fpclassifyF s_fmaxF s_fminF s_fdimF s_nanF s_truncF		  \
+	s_remquoF e_log2F e_exp2F s_roundF s_nearbyintF			  \
+	conjF cimagF crealF cabsF cargF s_cexpF s_csinhF s_ccoshF s_clogF \
+	s_catanF s_casinF s_ccosF s_csinF s_ctanF s_ctanhF s_cacosF	  \
+	s_casinhF s_cacoshF s_catanhF s_csqrtF s_cpowF s_cprojF		  \
+	s_fmaF s_lrintF s_llrintF s_lroundF s_llroundF e_exp10F w_log2F	  \
+	s_issignalingF k_casinhF					  \
+	k_standardF
+
+# GNU extensions for C (non TS 18661-3) types.
+gnu-libm-calls = \
+	e_j0F e_j1F e_jnF 						\
+	e_rem_pio2F e_scalbF						\
+	k_rem_pio2F							\
+	s_nexttowardF							\
+	s_significandF							\
+	w_j0F w_j1F w_jnF						\
+	w_scalbF							\
+	s_sincosF							\
+	s_clog10F							\
+	x2y2m1F								\
+	gamma_productF							\
+	lgamma_negF lgamma_productF					\
+	w_lgamma_compatF
+
+# Functions not strictly associated with a type, but required.
 libm-support = s_lib_version s_matherr s_signgam			\
 	       fclrexcpt fgetexcptflg fraiseexcpt fsetexcptflg		\
 	       ftestexcept fegetround fesetround fegetenv feholdexcpt	\
 	       fesetenv feupdateenv t_exp fedisblxcpt feenablxcpt	\
 	       fegetexcept
-libm-calls = e_acos e_acosh e_asin e_atan2 e_atanh e_cosh e_exp e_fmod	\
-	     e_hypot e_j0 e_j1 e_jn e_lgamma_r e_log e_log10 e_pow	\
-	     e_rem_pio2 e_remainder e_scalb e_sinh e_sqrt e_gamma_r	\
-	     e_ilogb							\
-	     k_cos k_rem_pio2 k_sin k_tan s_asinh s_atan s_cbrt		\
-	     s_ceil s_cos s_erf s_expm1 s_fabs				\
-	     s_floor s_log1p w_log1p s_logb				\
-	     s_nextafter s_nexttoward s_rint s_scalbln w_scalbln	\
-	     s_significand s_sin s_tan s_tanh w_acos w_acosh w_asin	\
-	     w_atan2 w_atanh w_cosh w_exp w_exp2 w_exp10 w_fmod		\
-	     w_tgamma w_hypot w_j0 w_j1 w_jn w_lgamma w_lgamma_r	\
-	     w_log w_log10 w_pow w_remainder w_scalb w_sinh w_sqrt	\
-	     w_ilogb							\
-	     s_fpclassify s_fmax s_fmin s_fdim s_nan s_trunc		\
-	     s_remquo e_log2 e_exp2 s_round s_nearbyint s_sincos	\
-	     conj cimag creal cabs carg s_cexp s_csinh s_ccosh s_clog	\
-	     s_catan s_casin s_ccos s_csin s_ctan s_ctanh s_cacos	\
-	     s_casinh s_cacosh s_catanh s_csqrt s_cpow s_cproj s_clog10 \
-	     s_fma s_lrint s_llrint s_lround s_llround e_exp10 w_log2	\
-	     s_issignaling $(calls:s_%=m_%) x2y2m1 k_casinh	\
-	     gamma_product k_standard lgamma_neg lgamma_product		\
-	     w_lgamma_compat
-
-dbl-only-routines := branred doasin dosincos halfulp mpa mpatan2	\
-		     mpatan mpexp mplog mpsqrt mptan sincos32 slowexp	\
-		     slowpow sincostab
-libm-routines = $(strip $(libm-support) $(libm-calls) \
-			$(patsubst %_rf,%f_r,$(libm-calls:=f))	\
-			$(long-m-$(long-double-fcts))) \
-		$(dbl-only-routines)
-long-m-routines = $(patsubst %_rl,%l_r,$(libm-calls:=l))
-long-m-support = t_sincosl k_sincosl
-long-m-yes = $(long-m-routines) $(long-m-support)
+
+# Type specific routine support.
+#
+# The following three variables control what is included for each type:
+#
+# type-floatN-suffix = The suffix of the type
+# type-floatN-routines = Type specific support objects
+# type-floatN-support-yes = A non-empty value if the type is supported
+#
+# TS 18661 derived types/formats should be conditionally added to
+# ext-types.
+#
+# Finally, note that types and ext-types are intentionally recursive
+# variables.  We only know the full set of supported types for the
+# target machine after the Rules makefile has been parsed.
+types = $(type-ldouble-$(long-double-fcts)) double float
+
+# long double support
+type-ldouble-suffix := l
+type-ldouble-routines := t_sincosl k_sincosl
+type-ldouble-yes := ldouble
+
+# double support
+type-double-suffix :=
+type-double-routines := branred doasin dosincos halfulp mpa mpatan2	\
+		       mpatan mpexp mplog mpsqrt mptan sincos32 slowexp	\
+		       slowpow sincostab
+
+# float support
+type-float-suffix := f
+type-float-routines :=
+
+# Extended type support (TS 18661)
+ext-types = $(types)
+
+# _Float128 support
+type-float128-suffix := f128
+type-float128-routines := $(type-ldouble-routines:l=f128)
+type-float128-yes := float128
+ext-types += $(type-float128-$(float128-fcts))
+
+# Apply suffix to an arbitrary set of types in arg 1 to arg 2
+bare-type-foreach = $(foreach t,$(1),$(subst F,$(type-$(t)-suffix),$(2)))
+
+# Apply suffix to each C type in arg 1
+type-foreach = $(call bare-type-foreach,$(types),$(1))
+
+# Likewise, but include TS 18661 types too.
+ext-type-foreach = $(call bare-type-foreach,$(ext-types),$(1))
+
+libm-routines = $(strip $(libm-support)					  \
+			$(call type-foreach, $(calls:s_%=m_%))		  \
+			$(call type-foreach, $(gnu-libm-calls))		  \
+			$(foreach t, $(ext-types), $(type-$(t)-routines)) \
+			$(call ext-type-foreach, $(ts-18661-calls)))	  \
 
 # These functions are in libc instead of libm because __printf_fp
 # calls them, so any program using printf will need them linked in,
 # and we don't want to have to link every program with -lm.
 # In libm-calls (above), list m_foo in place of s_foo for any
 # routine that should be compiled separately for its libc and libm versions.
-calls = s_isinf s_isnan s_finite s_copysign s_modf s_scalbn s_frexp s_ldexp \
-	s_signbit
-generated += $(foreach s,.c .S l.c l.S f.c f.S,$(calls:s_%=m_%$s))
-routines = $(calls) $(calls:=f) $(long-c-$(long-double-fcts))
-long-c-yes = $(calls:=l)
+calls = s_isinfF s_isnanF s_finiteF s_copysignF s_modfF s_scalbnF s_frexpF \
+	s_ldexpF s_signbitF
+generated += $(foreach s,.c .S,$(call ext-type-foreach, $(calls:s_%=m_%)))
+routines = $(call ext-type-foreach, $(calls))
 
 ifeq ($(build-mathvec),yes)
 # We need to install libm.so as linker script
@@ -120,9 +182,6 @@ tests-static = test-fpucw-static test-fpucw-ieee-static \
 	       test-signgam-uchar-static test-signgam-uchar-init-static \
 	       test-signgam-uint-static test-signgam-uint-init-static \
 	       test-signgam-ullong-static test-signgam-ullong-init-static
-# We do the `long double' tests only if this data type is available and
-# distinct from `double'.
-test-longdouble-yes = test-ldouble test-ildoubl test-ldouble-finite
 
 ifneq (,$(CXX))
 tests += test-math-isinff
@@ -130,9 +189,17 @@ endif
 
 ifneq (no,$(PERL))
 libm-vec-tests = $(addprefix test-,$(libmvec-tests))
-libm-tests = test-float test-double $(test-longdouble-$(long-double-fcts)) \
-	test-ifloat test-idouble test-float-finite test-double-finite \
-	$(libm-vec-tests)
+
+# Tests for each type defined by libm
+libm-noi-tests = $(foreach t,$(ext-types),test-$t)
+libm-fin-tests = $(foreach t,$(ext-types),test-$t-finite)
+libm-inl-tests = $(foreach t,$(ext-types),$(subst ldouble,ldoubl,test-i$t))
+
+# Include all typed tests for finite/inline/default.
+libm-type-tests = $(libm-noi-tests) $(libm-fin-tests) $(libm-inl-tests)
+
+libm-tests = $(libm-type-tests) $(libm-vec-tests)
+
 libm-tests.o = $(addsuffix .o,$(libm-tests))
 
 tests += $(libm-tests)
@@ -155,16 +222,6 @@ $(objpfx)libm-test.stmp: $(ulps-file) libm-test.inc gen-libm-test.pl \
 	$(PERL) gen-libm-test.pl -u $< -o "$(objpfx)"
 	$(SHELL) gen-libm-have-vector-test.sh > $(objpfx)libm-have-vector-test.h
 	@echo > $@
-
-$(objpfx)test-float.o: $(objpfx)libm-test.stmp
-$(objpfx)test-ifloat.o: $(objpfx)libm-test.stmp
-$(objpfx)test-float-finite.o: $(objpfx)libm-test.stmp
-$(objpfx)test-double.o: $(objpfx)libm-test.stmp
-$(objpfx)test-idouble.o: $(objpfx)libm-test.stmp
-$(objpfx)test-double-finite.o: $(objpfx)libm-test.stmp
-$(objpfx)test-ldouble.o: $(objpfx)libm-test.stmp
-$(objpfx)test-ildoubl.o: $(objpfx)libm-test.stmp
-$(objpfx)test-ldouble-finite.o: $(objpfx)libm-test.stmp
 endif
 
 libm-test-fast-math-cflags = -fno-builtin -D__FAST_MATH__ -DTEST_FAST_MATH
@@ -197,12 +254,7 @@ libm-test-no-inline-cflags = -fno-inline -ffloat-store -fno-builtin \
 			     -fsignaling-nans
 libm-test-finite-cflags = $(libm-test-no-inline-cflags) \
 			  -U__FINITE_MATH_ONLY__ -D__FINITE_MATH_ONLY__=1
-CFLAGS-test-float.c = $(libm-test-no-inline-cflags)
-CFLAGS-test-float-finite.c = $(libm-test-finite-cflags)
-CFLAGS-test-double.c = $(libm-test-no-inline-cflags)
-CFLAGS-test-double-finite.c = $(libm-test-finite-cflags)
-CFLAGS-test-ldouble.c = $(libm-test-no-inline-cflags)
-CFLAGS-test-ldouble-finite.c = $(libm-test-finite-cflags)
+
 CFLAGS-test-tgmath.c = -fno-builtin
 # The following testcase uses very long lines (>3 million), so it may take a
 # while to compile it. See: http://llvm.org/bugs/show_bug.cgi?id=14106 and
@@ -212,12 +264,6 @@ CFLAGS-test-tgmath-ret.c = -fno-builtin
 CFLAGS-test-powl.c = -fno-builtin
 
 CFLAGS-test-snan.c = -fsignaling-nans
-CPPFLAGS-test-ifloat.c = -U__LIBC_INTERNAL_MATH_INLINES \
-			 $(libm-test-fast-math-cflags)
-CPPFLAGS-test-idouble.c = -U__LIBC_INTERNAL_MATH_INLINES \
-			  $(libm-test-fast-math-cflags)
-CPPFLAGS-test-ildoubl.c = -U__LIBC_INTERNAL_MATH_INLINES \
-			  $(libm-test-fast-math-cflags)
 
 CFLAGS-test-signgam-finite.c = -ffinite-math-only
 CFLAGS-test-signgam-finite-c99.c = -ffinite-math-only -std=c99
@@ -249,6 +295,21 @@ ifneq (no,$(PERL))
 # This must come after the inclusion of sysdeps Makefiles via Rules.
 $(addprefix $(objpfx), $(addsuffix .o, $(libm-vec-tests))): $(objpfx)libm-test.stmp
 
+# Likewise, we only know what types actually exist for the machine once all
+# the sysdep Makefiles are parsed. (i.e long-double-fcts)
+$(foreach t,$(libm-type-tests), \
+	$(eval $$(objpfx)$(t).o: $$(objpfx)libm-test.stmp))
+
+# Add appropriate CPPFLAGS to the inline tests
+$(foreach t,$(libm-inl-tests),$(eval CPPFLAGS-$(t).c = \
+	-U__LIBC_INTERNAL_MATH_INLINES $$(libm-test-fast-math-cflags)))
+
+# Add appropriate CFLAGS to the no-inline tests.
+$(foreach t,$(libm-noi-tests),$(eval CFLAGS-$(t).c = $$(libm-test-no-inline-cflags)))
+
+# Add appropriate CFLAGS to the finite tests
+$(foreach t,$(libm-fin-tests),$(eval CFLAGS-$(t).c = $$(libm-test-finite-cflags)))
+
 # Run the math programs to automatically generate ULPs files.
 .PHONY: regen-ulps
 
-- 
2.4.11

>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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]