Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Wed, 26 Nov 2014 14:07:55 +0100
From: Jens Gustedt <>
Subject: [PATCH 1/4] the CMPLX macros must be usable in initializations of
 static variables

Because of some boundary cases for infinities and negative zeros, doing
this properly is only possible with either support for _Imaginary or some
compiler magic.

For the moment, we only know such magic for clang and gcc. There it is
only available for newer compilers. Therefore we make the CMPLX macros
only available when in C11 mode (or actually even in C1X mode).

Internally for the compilation of the complex functions of the math
library we use such a macro, but that doesn't have the constraint of
being usable for static initializations. So if we are not in C11, we
provide such a macro as __CMPLX_NC in complex.h and map the CMPLX macros
internally to that.

As an effect this reverts commit faea4c9937d36b17e53fdc7d5a254d7e936e1755.
 include/complex.h   | 30 ++++++++++++++++++++++++++++--
 src/internal/libm.h |  8 ++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/complex.h b/include/complex.h
index 13a45c5..e88cf13 100644
--- a/include/complex.h
+++ b/include/complex.h
@@ -112,12 +112,38 @@ long double creall(long double complex);
 #define cimagf(x) __CIMAG(x, float)
 #define cimagl(x) __CIMAG(x, long double)
-#define __CMPLX(x, y, t) \
-	((union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z)
+#ifdef _Imaginary_I
+# define __CMPLX(x, y, t) ((t)(x) + _Imaginary_I*(t)(y))
+# define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y))
+#ifndef __CMPLX
+# if defined(__clang__)
+  /* Clang allows initializer lists for complex numbers and compound
+     literals for the initialization of static variables. */
+#  define __CMPLX(x, y, t) (+(_Complex t){ (x), (y) })
+# elif 100*__GNUC__+__GNUC_MINOR__ >= 407
+#  define __CMPLX(x, y, t) __builtin_complex((t)(x), (t)(y))
+# endif
+#ifndef __CMPLX
+# if __STDC_VERSION__ >= 201000L
+#  warning for this compiler, macros CMPLX, CMPLXF and CMPLXL are not standard
+#  warning conforming for infinities and signed zeros
+#  define __CMPLX(x, y, t) __CMPLX_I(x, y, t)
+# endif
+# define __CMPLX_NC(x, y, t) (+(union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z)
+# define __CMPLX_NC(x, y, t) __CMPLX(x, y, t)
+#if __STDC_VERSION__ >= 201000L
 #define CMPLX(x, y) __CMPLX(x, y, double)
 #define CMPLXF(x, y) __CMPLX(x, y, float)
 #define CMPLXL(x, y) __CMPLX(x, y, long double)
 #ifdef __cplusplus
diff --git a/src/internal/libm.h b/src/internal/libm.h
index ebcd784..f916e2e 100644
--- a/src/internal/libm.h
+++ b/src/internal/libm.h
@@ -155,4 +155,12 @@ long double __tanl(long double, long double, int);
 long double __polevll(long double, const long double *, int);
 long double __p1evll(long double, const long double *, int);
+/* complex */
+#ifndef CMPLX
+#define CMPLX(x, y) __CMPLX_NC(x, y, double)
+#define CMPLXF(x, y) __CMPLX_NC(x, y, float)
+#define CMPLXL(x, y) __CMPLX_NC(x, y, long double)

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.