+#define __LDBLCX(x) (__IS_CX(x) && sizeof(x) == sizeof(long double complex) && sizeof(long double) != sizeof(double))
+
+/* return type */
+
+#ifdef __GNUC__
+/* cast to double when x is integral, otherwise use typeof(x) */
+#define __RETCAST(x) (__typeof__(*( \
+ 0 ? (__typeof__(0 ? (double *)0 : (void *)__IS_FP(x)))0 : \
+ (__typeof__(0 ? (__typeof__(x) *)0 : (void *)!__IS_FP(x)))0 )))
+/* 2 args case, consider complex types (for cpow) */
+#define __RETCAST_2(x, y) (__typeof__(*( \
+ 0 ? (__typeof__(0 ? (double *)0 : \
+ (void *)!((!__IS_FP(x) || !__IS_FP(y)) && __FLT((x)+(y)+1.0f))))0 : \
+ 0 ? (__typeof__(0 ? (double complex *)0 : \
+ (void *)!((!__IS_FP(x) || !__IS_FP(y)) && __FLTCX((x)+(y)))))0 : \
+ (__typeof__(0 ? (__typeof__((x)+(y)) *)0 : \
+ (void *)((!__IS_FP(x) || !__IS_FP(y)) && (__FLT((x)+(y)+1.0f) || __FLTCX((x)+(y))))))0 )))
+/* 3 args case, don't consider complex types (fma only) */
+#define __RETCAST_3(x, y, z) (__typeof__(*( \
+ 0 ? (__typeof__(0 ? (double *)0 : \
+ (void *)!((!__IS_FP(x) || !__IS_FP(y) || !__IS_FP(z)) && __FLT((x)+(y)+(z)+1.0f))))0 : \
+ (__typeof__(0 ? (__typeof__((x)+(y)) *)0 : \
+ (void *)((!__IS_FP(x) || !__IS_FP(y) || !__IS_FP(z)) && __FLT((x)+(y)+(z)+1.0f))))0 )))
+/* drop complex from the type of x */
+#define __TO_REAL(x) *( \
+ 0 ? (__typeof__(0 ? (double *)0 : (void *)!__DBLCX(x)))0 : \
+ 0 ? (__typeof__(0 ? (float *)0 : (void *)!__FLTCX(x)))0 : \
+ 0 ? (__typeof__(0 ? (long double *)0 : (void *)!__LDBLCX(x)))0 : \
+ (__typeof__(0 ? (__typeof__(x) *)0 : (void *)__IS_CX(x)))0 )
+#else
+#define __RETCAST(x)
+#define __RETCAST_2(x, y)
+#define __RETCAST_3(x, y, z)
+#endif