Kaynağa Gözat

Move CMPLX() into <openlibm_complex.h>, as it is normally part of <complex.h>.

While there, make CMPLX() work with Clang by using compound literals.
Now that cimag*() uses __imag__, we can also just inline the unions.
There is no need for the separate types anymore.

Also just define CMPLX() unconditionally now, as we no longer pull in
the host's <complex.h>.
Ed Schouten 10 yıl önce
ebeveyn
işleme
410e6ebb59
2 değiştirilmiş dosya ile 68 ekleme ve 98 silme
  1. 0 98
      src/openlibm.h
  2. 68 0
      src/openlibm_complex.h

+ 0 - 98
src/openlibm.h

@@ -17,8 +17,6 @@
 #ifndef OPENLIBM_H
 #define	OPENLIBM_H
 
-#include <openlibm_complex.h>
-
 #if (defined(_WIN32) || defined (_MSC_VER)) && !defined(__WIN32__)
     #define __WIN32__
 #endif
@@ -180,102 +178,6 @@ extern int signgam;
 #endif
 #endif /* __BSD_VISIBLE */
 
-//VBS
-//#ifdef _COMPLEX_H
-
-/*
- * C99 specifies that complex numbers have the same representation as
- * an array of two elements, where the first element is the real part
- * and the second element is the imaginary part.
- */
-typedef union {
-	float complex f;
-	float a[2];
-} float_complex;
-typedef union {
-	double complex f;
-	double a[2];
-} double_complex;
-typedef union {
-	long double complex f;
-	long double a[2];
-} long_double_complex;
-#define	REALPART(z)	((z).a[0])
-#define	IMAGPART(z)	((z).a[1])
-
-/*
- * Macros that can be used to construct complex values.
- *
- * The C99 standard intends x+I*y to be used for this, but x+I*y is
- * currently unusable in general since gcc introduces many overflow,
- * underflow, sign and efficiency bugs by rewriting I*y as
- * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
- * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
- * to -0.0+I*0.0.
- *
- * In C11, a CMPLX(x,y) macro was added to circumvent this limitation,
- * and gcc 4.7 added a __builtin_complex feature to simplify implementation
- * of CMPLX in libc, so we can take advantage of these features if they
- * are available.
- *
- * If __builtin_complex is not available, resort to using inline
- * functions instead. These can unfortunately not be used to construct
- * compile-time constants.
- */
-
-#define HAVE_BUILTIN_COMPLEX (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__INTEL_COMPILER)
-
-#ifndef CMPLXF
-#if HAVE_BUILTIN_COMPLEX
-#  define CMPLXF(x,y) __builtin_complex ((float) (x), (float) (y))
-#else
-static __inline float complex
-CMPLXF(float x, float y)
-{
-	float_complex z;
-
-	REALPART(z) = x;
-	IMAGPART(z) = y;
-	return (z.f);
-}
-#endif
-#endif
-
-#ifndef CMPLX
-#if HAVE_BUILTIN_COMPLEX
-#  define CMPLX(x,y) __builtin_complex ((double) (x), (double) (y))
-#else
-static __inline double complex
-CMPLX(double x, double y)
-{
-	double_complex z;
-
-	REALPART(z) = x;
-	IMAGPART(z) = y;
-	return (z.f);
-}
-#endif
-#endif
-
-#ifndef CMPLXL
-#if HAVE_BUILTIN_COMPLEX
-#  define CMPLXL(x,y) __builtin_complex ((long double) (x), (long double) (y))
-#else
-static __inline long double complex
-CMPLXL(long double x, long double y)
-{
-	long_double_complex z;
-
-	REALPART(z) = x;
-	IMAGPART(z) = y;
-	return (z.f);
-}
-#endif
-#endif
-
-//VBS
-//#endif /* _COMPLEX_H */
-
 /*
  * Most of these functions depend on the rounding mode and have the side
  * effect of raising floating-point exceptions, so they are not declared

+ 68 - 0
src/openlibm_complex.h

@@ -23,6 +23,74 @@
 #define _Complex_I 1.0fi
 #define I _Complex_I
 
+/*
+ * Macros that can be used to construct complex values.
+ *
+ * The C99 standard intends x+I*y to be used for this, but x+I*y is
+ * currently unusable in general since gcc introduces many overflow,
+ * underflow, sign and efficiency bugs by rewriting I*y as
+ * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
+ * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
+ * to -0.0+I*0.0.
+ *
+ * In C11, a CMPLX(x,y) macro was added to circumvent this limitation,
+ * and gcc 4.7 added a __builtin_complex feature to simplify implementation
+ * of CMPLX in libc, so we can take advantage of these features if they
+ * are available. Clang simply allows complex values to be constructed
+ * using a compound literal.
+ *
+ * If __builtin_complex is not available, resort to using inline
+ * functions instead. These can unfortunately not be used to construct
+ * compile-time constants.
+ *
+ * C99 specifies that complex numbers have the same representation as
+ * an array of two elements, where the first element is the real part
+ * and the second element is the imaginary part.
+ */
+
+#ifdef __clang__
+#  define CMPLXF(x, y) ((float complex){x, y})
+#  define CMPLX(x, y) ((double complex){x, y})
+#  define CMPLXL(x, y) ((long double complex){x, y})
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__INTEL_COMPILER)
+#  define CMPLXF(x,y) __builtin_complex ((float) (x), (float) (y))
+#  define CMPLX(x,y) __builtin_complex ((double) (x), (double) (y))
+#  define CMPLXL(x,y) __builtin_complex ((long double) (x), (long double) (y))
+#else
+static inline float complex
+CMPLXF(float x, float y)
+{
+	union {
+		float a[2];
+		float complex f;
+	} z = {{ x, y }};
+
+	return (z.f);
+}
+
+static inline double complex
+CMPLX(double x, double y)
+{
+	union {
+		double a[2];
+		double complex f;
+	} z = {{ x, y }};
+
+	return (z.f);
+}
+
+static inline long double complex
+CMPLXL(long double x, long double y)
+{
+	union {
+		long double a[2];
+		long double complex f;
+	} z = {{ x, y }};
+
+	return (z.f);
+}
+#endif
+
 /*
  * Double versions of C99 functions
  */