Skip to content

Commit 410e6eb

Browse files
committed
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>.
1 parent a249c5e commit 410e6eb

2 files changed

Lines changed: 68 additions & 98 deletions

File tree

src/openlibm.h

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
#ifndef OPENLIBM_H
1818
#define OPENLIBM_H
1919

20-
#include <openlibm_complex.h>
21-
2220
#if (defined(_WIN32) || defined (_MSC_VER)) && !defined(__WIN32__)
2321
#define __WIN32__
2422
#endif
@@ -180,102 +178,6 @@ extern int signgam;
180178
#endif
181179
#endif /* __BSD_VISIBLE */
182180

183-
//VBS
184-
//#ifdef _COMPLEX_H
185-
186-
/*
187-
* C99 specifies that complex numbers have the same representation as
188-
* an array of two elements, where the first element is the real part
189-
* and the second element is the imaginary part.
190-
*/
191-
typedef union {
192-
float complex f;
193-
float a[2];
194-
} float_complex;
195-
typedef union {
196-
double complex f;
197-
double a[2];
198-
} double_complex;
199-
typedef union {
200-
long double complex f;
201-
long double a[2];
202-
} long_double_complex;
203-
#define REALPART(z) ((z).a[0])
204-
#define IMAGPART(z) ((z).a[1])
205-
206-
/*
207-
* Macros that can be used to construct complex values.
208-
*
209-
* The C99 standard intends x+I*y to be used for this, but x+I*y is
210-
* currently unusable in general since gcc introduces many overflow,
211-
* underflow, sign and efficiency bugs by rewriting I*y as
212-
* (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
213-
* In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
214-
* to -0.0+I*0.0.
215-
*
216-
* In C11, a CMPLX(x,y) macro was added to circumvent this limitation,
217-
* and gcc 4.7 added a __builtin_complex feature to simplify implementation
218-
* of CMPLX in libc, so we can take advantage of these features if they
219-
* are available.
220-
*
221-
* If __builtin_complex is not available, resort to using inline
222-
* functions instead. These can unfortunately not be used to construct
223-
* compile-time constants.
224-
*/
225-
226-
#define HAVE_BUILTIN_COMPLEX (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__INTEL_COMPILER)
227-
228-
#ifndef CMPLXF
229-
#if HAVE_BUILTIN_COMPLEX
230-
# define CMPLXF(x,y) __builtin_complex ((float) (x), (float) (y))
231-
#else
232-
static __inline float complex
233-
CMPLXF(float x, float y)
234-
{
235-
float_complex z;
236-
237-
REALPART(z) = x;
238-
IMAGPART(z) = y;
239-
return (z.f);
240-
}
241-
#endif
242-
#endif
243-
244-
#ifndef CMPLX
245-
#if HAVE_BUILTIN_COMPLEX
246-
# define CMPLX(x,y) __builtin_complex ((double) (x), (double) (y))
247-
#else
248-
static __inline double complex
249-
CMPLX(double x, double y)
250-
{
251-
double_complex z;
252-
253-
REALPART(z) = x;
254-
IMAGPART(z) = y;
255-
return (z.f);
256-
}
257-
#endif
258-
#endif
259-
260-
#ifndef CMPLXL
261-
#if HAVE_BUILTIN_COMPLEX
262-
# define CMPLXL(x,y) __builtin_complex ((long double) (x), (long double) (y))
263-
#else
264-
static __inline long double complex
265-
CMPLXL(long double x, long double y)
266-
{
267-
long_double_complex z;
268-
269-
REALPART(z) = x;
270-
IMAGPART(z) = y;
271-
return (z.f);
272-
}
273-
#endif
274-
#endif
275-
276-
//VBS
277-
//#endif /* _COMPLEX_H */
278-
279181
/*
280182
* Most of these functions depend on the rounding mode and have the side
281183
* effect of raising floating-point exceptions, so they are not declared

src/openlibm_complex.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,74 @@
2323
#define _Complex_I 1.0fi
2424
#define I _Complex_I
2525

26+
/*
27+
* Macros that can be used to construct complex values.
28+
*
29+
* The C99 standard intends x+I*y to be used for this, but x+I*y is
30+
* currently unusable in general since gcc introduces many overflow,
31+
* underflow, sign and efficiency bugs by rewriting I*y as
32+
* (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
33+
* In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
34+
* to -0.0+I*0.0.
35+
*
36+
* In C11, a CMPLX(x,y) macro was added to circumvent this limitation,
37+
* and gcc 4.7 added a __builtin_complex feature to simplify implementation
38+
* of CMPLX in libc, so we can take advantage of these features if they
39+
* are available. Clang simply allows complex values to be constructed
40+
* using a compound literal.
41+
*
42+
* If __builtin_complex is not available, resort to using inline
43+
* functions instead. These can unfortunately not be used to construct
44+
* compile-time constants.
45+
*
46+
* C99 specifies that complex numbers have the same representation as
47+
* an array of two elements, where the first element is the real part
48+
* and the second element is the imaginary part.
49+
*/
50+
51+
#ifdef __clang__
52+
# define CMPLXF(x, y) ((float complex){x, y})
53+
# define CMPLX(x, y) ((double complex){x, y})
54+
# define CMPLXL(x, y) ((long double complex){x, y})
55+
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__INTEL_COMPILER)
56+
# define CMPLXF(x,y) __builtin_complex ((float) (x), (float) (y))
57+
# define CMPLX(x,y) __builtin_complex ((double) (x), (double) (y))
58+
# define CMPLXL(x,y) __builtin_complex ((long double) (x), (long double) (y))
59+
#else
60+
static inline float complex
61+
CMPLXF(float x, float y)
62+
{
63+
union {
64+
float a[2];
65+
float complex f;
66+
} z = {{ x, y }};
67+
68+
return (z.f);
69+
}
70+
71+
static inline double complex
72+
CMPLX(double x, double y)
73+
{
74+
union {
75+
double a[2];
76+
double complex f;
77+
} z = {{ x, y }};
78+
79+
return (z.f);
80+
}
81+
82+
static inline long double complex
83+
CMPLXL(long double x, long double y)
84+
{
85+
union {
86+
long double a[2];
87+
long double complex f;
88+
} z = {{ x, y }};
89+
90+
return (z.f);
91+
}
92+
#endif
93+
2694
/*
2795
* Double versions of C99 functions
2896
*/

0 commit comments

Comments
 (0)