* [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables @ 2014-11-26 13:07 Jens Gustedt 2014-12-02 17:49 ` Rich Felker 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-11-26 13:07 UTC (permalink / raw) To: musl 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)) +#else +# define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y)) +#endif + +#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 +#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) +#else +# define __CMPLX_NC(x, y, t) __CMPLX(x, y, t) +#endif + +#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) +#endif #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) +#endif + #endif -- 1.9.1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-26 13:07 [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables Jens Gustedt @ 2014-12-02 17:49 ` Rich Felker 2014-12-02 19:10 ` Jens Gustedt 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2014-12-02 17:49 UTC (permalink / raw) To: musl On Wed, Nov 26, 2014 at 02:07:55PM +0100, Jens Gustedt wrote: > 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)) > +#else > +# define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > +#endif I was wondering about the purpose of the casts here, and I got to thinking: what is the behavior supposed to be with regards to excess precision? Before it was truncated by type punning and now it's truncated by cast. But without the cast it would not be truncated. Which behavior is right? > +#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 > +#endif Does clang not support the GCC builtin? I would highly prefer not to use the clang form since it's a compiler bug that should be fixed in future clang. > +#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) > +#else > +# define __CMPLX_NC(x, y, t) __CMPLX(x, y, t) > +#endif > + > +#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) > +#endif __CMPLX_NC is for internal use only and has no reason to be in the public header. Also I'd like to keep the behavior in the public header a lot more explicit rather than having lots of nested conditionals and #ifndef __CMPLX where it's necessary to track back through all the conditions to reason about which case gets used. My preference would be if we could just define CMPLX either in terms of __builtin_complex, and only exposing it in C11 mode. _Imaginary_I is not supported yet at all and would require further changes to this header to add anyway (this header is responsible for defining it), so conditioning on its definition is not meaningful. And pre-4.7 versions of GCC don't support C11 anyway (and even 4.7 and 4.8 are highly incomplete) so I don't think much is lost if a C11 feature fails to work on older compilers. The big question is how this fares for clang compatibility though. I expect pcc and cparser/firm will provide a compatible __builtin_complex (if they don't already) as they improve C11 support. > 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) > +#endif > + > #endif This should probably use the unions unconditionally, after including complex.h and #undef'ing CMPLX[FL], since musl does not require a C11 compiler to build it. Depending on whether a fallback is provided for old compilers or not, I think your approach could lead to musl being miscompiled. It probably doesn't happen since CMPLX is no longer exposed except in C11 mode, and musl is compiled with -std=c99, but this looks fragile and could cause breakage to go unnoticed if we switch to preferring -std=c11 some time later. (There's been talk of preferring -std=c11 if it works.) Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-02 17:49 ` Rich Felker @ 2014-12-02 19:10 ` Jens Gustedt 2014-12-02 19:42 ` Rich Felker 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-12-02 19:10 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 7729 bytes --] Hello, Am Dienstag, den 02.12.2014, 12:49 -0500 schrieb Rich Felker: > On Wed, Nov 26, 2014 at 02:07:55PM +0100, Jens Gustedt wrote: > > 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)) > > +#else > > +# define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > > +#endif > > I was wondering about the purpose of the casts here, and I got to > thinking: what is the behavior supposed to be with regards to excess > precision? > Before it was truncated by type punning no, before the conversion was implicit in the initializer, I think > and now it's > truncated by cast. But without the cast it would not be truncated. > Which behavior is right? The reason for the cast is simple, the returned type must be `_Complex t` and nothing else. This could otherwise be achived by casting the result to `_Complex t`, but the requirements for the macros are expressed as those of function interfaces, so a separate conversion of each of the arguments is in order. > > +#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 > > +#endif > > Does clang not support the GCC builtin? no, and I don't have the impression they will. They invented their own internals for this, as you can see here. > I would highly prefer not to > use the clang form since it's a compiler bug that should be fixed in > future clang. clang only claims to support gcc builtins up to 4.2, I think. For the others they do it "à la carte", and __builtin_complex is quite recent, so it may take a while, if ever. We could use their feature test macros for that, but for the moment we don't have anything like that, I think. > > +#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) > > +#else > > +# define __CMPLX_NC(x, y, t) __CMPLX(x, y, t) > > +#endif > > + > > +#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) > > +#endif > > __CMPLX_NC is for internal use only and has no reason to be in the > public header. right, no problem, I'll push it into libm.h > Also I'd like to keep the behavior in the public header > a lot more explicit rather than having lots of nested conditionals and > #ifndef __CMPLX where it's necessary to track back through all the > conditions to reason about which case gets used. yes, me too, as I already said earlier (but in case of errors both, gcc and clang are quite good now in tracking down to the real definition) > My preference would be if we could just define CMPLX either in terms > of __builtin_complex, not possible, I think > and only exposing it in C11 mode. this is already the case. (Or is it C1x that bothers you?) > _Imaginary_I > is not supported yet at all and would require further changes to this > header to add anyway (this header is responsible for defining it), so > conditioning on its definition is not meaningful. I am not sure of that. It could also come directly from the compiler just as it defines some __SOMETHING__ macros before any include > And pre-4.7 versions > of GCC don't support C11 anyway (and even 4.7 and 4.8 are highly > incomplete) so I don't think much is lost if a C11 feature fails to > work on older compilers. as said, there is no intention to support it for older compilers. So I read it that you want me to pull the definition of the __CMPLX versions into the C1x conditional? > The big question is how this fares for clang > compatibility though. I expect pcc and cparser/firm will provide a > compatible __builtin_complex (if they don't already) as they improve > C11 support. > > > 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) > > +#endif > > + > > #endif > > This should probably use the unions unconditionally, after including > complex.h and #undef'ing CMPLX[FL], since musl does not require a C11 > compiler to build it. Depending on whether a fallback is provided for > old compilers or not, I think your approach could lead to musl being > miscompiled. It probably doesn't happen since CMPLX is no longer > exposed except in C11 mode, and musl is compiled with -std=c99, but > this looks fragile and could cause breakage to go unnoticed if we > switch to preferring -std=c11 some time later. (There's been talk of > preferring -std=c11 if it works.) Hm, clearly not my preference. I think we should use the right tool (which is __builtin_complex for gcc or the bogus initializer for clang) as soon as we have it. This is why I wanted to have the detection of the features as early as possible where it belongs to my opinion, complex.h. They have more chances to optimize things correctly without temporaries even when compiled without optimization. Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-02 19:10 ` Jens Gustedt @ 2014-12-02 19:42 ` Rich Felker 2014-12-02 22:00 ` Jens Gustedt 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2014-12-02 19:42 UTC (permalink / raw) To: musl On Tue, Dec 02, 2014 at 08:10:32PM +0100, Jens Gustedt wrote: > Hello, > > Am Dienstag, den 02.12.2014, 12:49 -0500 schrieb Rich Felker: > > On Wed, Nov 26, 2014 at 02:07:55PM +0100, Jens Gustedt wrote: > > > 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)) > > > +#else > > > +# define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > > > +#endif > > > > I was wondering about the purpose of the casts here, and I got to > > thinking: what is the behavior supposed to be with regards to excess > > precision? > > > Before it was truncated by type punning > > no, before the conversion was implicit in the initializer, I think Yes, sorry I was imprecise. > > and now it's > > truncated by cast. But without the cast it would not be truncated. > > Which behavior is right? > > The reason for the cast is simple, the returned type must be > `_Complex t` and nothing else. I see. > This could otherwise be achived by casting the result to `_Complex t`, > but the requirements for the macros are expressed as those of function > interfaces, so a separate conversion of each of the arguments is in > order. Perhaps it could also be achieved via some other means of coercing an appropriate type, but given the paragraph 4 note in the standard, I'm happy with the casts. > > > +#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 > > > +#endif > > > > Does clang not support the GCC builtin? > > no, and I don't have the impression they will. They invented their own > internals for this, as you can see here. Yes, but their form is a bug that needs to be removed, so they'll have to add something in its place, and __builtin_complex is the natural choice. For what it's worth, glibc only supports __builtin_complex and just does not define these macros at all if it's not supported. > > Also I'd like to keep the behavior in the public header > > a lot more explicit rather than having lots of nested conditionals and > > #ifndef __CMPLX where it's necessary to track back through all the > > conditions to reason about which case gets used. > > yes, me too, as I already said earlier > > (but in case of errors both, gcc and clang are quite good now in > tracking down to the real definition) In the case of reporting warnings/errors, yes. But in case a user is trying to figure out which definition is getting used because it's relevant to a bug they're facing in their program, #ifdef mazes are a pain. > > My preference would be if we could just define CMPLX either in terms > > of __builtin_complex, > > not possible, I think Well, it's what glibc does. That's not to say it's a good choice, but it suggests there could be pressure to get other compilers to support it. > > and only exposing it in C11 mode. > > this is already the case. (Or is it C1x that bothers you?) I did find the 201000L comparison a bit odd (is that the "C1x" thing?) but my comment here wasn't in reference to your proposal being different from the ideal I'd like to have, just a statement of the latter. > > _Imaginary_I > > is not supported yet at all and would require further changes to this > > header to add anyway (this header is responsible for defining it), so > > conditioning on its definition is not meaningful. > > I am not sure of that. It could also come directly from the compiler > just as it defines some __SOMETHING__ macros before any include I don't think so. Consider: #undef _Imaginary_I #include <complex.h> Perhaps this is non-conforming for technical reasons, but the standard is fairly direct in saying that complex.h defines the _Imaginary_I macro rather than just having it predefined. > > And pre-4.7 versions > > of GCC don't support C11 anyway (and even 4.7 and 4.8 are highly > > incomplete) so I don't think much is lost if a C11 feature fails to > > work on older compilers. > > as said, there is no intention to support it for older compilers. So I > read it that you want me to pull the definition of the __CMPLX > versions into the C1x conditional? I'm not sure I follow what you're saying here. The text you quoted was in regards to my hope of just having a single definition, not a specific request for any particular changes to your proposed patch. > > The big question is how this fares for clang > > compatibility though. I expect pcc and cparser/firm will provide a > > compatible __builtin_complex (if they don't already) as they improve > > C11 support. > > > > > 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) > > > +#endif > > > + > > > #endif > > > > This should probably use the unions unconditionally, after including > > complex.h and #undef'ing CMPLX[FL], since musl does not require a C11 > > compiler to build it. Depending on whether a fallback is provided for > > old compilers or not, I think your approach could lead to musl being > > miscompiled. It probably doesn't happen since CMPLX is no longer > > exposed except in C11 mode, and musl is compiled with -std=c99, but > > this looks fragile and could cause breakage to go unnoticed if we > > switch to preferring -std=c11 some time later. (There's been talk of > > preferring -std=c11 if it works.) > > Hm, clearly not my preference. I think we should use the right tool > (which is __builtin_complex for gcc or the bogus initializer for > clang) as soon as we have it. > > This is why I wanted to have the detection of the features as early as > possible where it belongs to my opinion, complex.h. > > They have more chances to optimize things correctly without > temporaries even when compiled without optimization. As stated in another thread, my preference is highly towards not having multiple versions of the same code, especially when one or more are unlikely to get good testing. The "more chance to optimize" argument does not apply unless there really are compilers which compile the unions poorly (not counting intentional non-optimizing modes) and I'm not aware of any. Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-02 19:42 ` Rich Felker @ 2014-12-02 22:00 ` Jens Gustedt 2014-12-02 22:47 ` Rich Felker 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-12-02 22:00 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 6194 bytes --] Am Dienstag, den 02.12.2014, 14:42 -0500 schrieb Rich Felker: > On Tue, Dec 02, 2014 at 08:10:32PM +0100, Jens Gustedt wrote: > > > Does clang not support the GCC builtin? > > > > no, and I don't have the impression they will. They invented their own > > internals for this, as you can see here. > > Yes, but their form is a bug that needs to be removed, so they'll have > to add something in its place, and __builtin_complex is the natural > choice. For what it's worth, glibc only supports __builtin_complex and > just does not define these macros at all if it's not supported. you mean it is a bug because the two-value-initializer is a constraint violation? It only is a bug that has to be diagnosed if user code is using it. Internals as long they are not visible to the user isn't covered by this, I think. And this is exactly the reason why the macros have been introduced in C11, to hide such cruft from the user's eye :) > > > My preference would be if we could just define CMPLX either in terms > > > of __builtin_complex, > > > > not possible, I think > > Well, it's what glibc does. That's not to say it's a good choice, but > it suggests there could be pressure to get other compilers to support > it. and that's then one of the points where they aren't C11 conforming when compiled with other compilers > > > and only exposing it in C11 mode. > > > > this is already the case. (Or is it C1x that bothers you?) > > I did find the 201000L comparison a bit odd (is that the "C1x" thing?) yes > but my comment here wasn't in reference to your proposal being > different from the ideal I'd like to have, just a statement of the > latter. ok > > > _Imaginary_I > > > is not supported yet at all and would require further changes to this > > > header to add anyway (this header is responsible for defining it), so > > > conditioning on its definition is not meaningful. > > > > I am not sure of that. It could also come directly from the compiler > > just as it defines some __SOMETHING__ macros before any include > > I don't think so. Consider: > > #undef _Imaginary_I > #include <complex.h> > > Perhaps this is non-conforming for technical reasons, it is non-conforming > but the standard > is fairly direct in saying that complex.h defines the _Imaginary_I > macro rather than just having it predefined. but it also says » Implementations that define the macro __STDC_NO_COMPLEX__ need not provide » this header nor support any of its facilities. so any of the facilities *may* be provided anyhow. (and since _Imaginary_I is reserved it is allowed to do that in any case.) But if you want to avoid that branch, I understand. _Imaginary_I would be *the* way to solve all of this easily, sigh. > > > And pre-4.7 versions > > > of GCC don't support C11 anyway (and even 4.7 and 4.8 are highly > > > incomplete) so I don't think much is lost if a C11 feature fails to > > > work on older compilers. > > > > as said, there is no intention to support it for older compilers. So I > > read it that you want me to pull the definition of the __CMPLX > > versions into the C1x conditional? > > I'm not sure I follow what you're saying here. The text you quoted was > in regards to my hope of just having a single definition, not a > specific request for any particular changes to your proposed patch. > > > > The big question is how this fares for clang > > > compatibility though. I expect pcc and cparser/firm will provide a > > > compatible __builtin_complex (if they don't already) as they improve > > > C11 support. > > > > > > > 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) > > > > +#endif > > > > + > > > > #endif > > > > > > This should probably use the unions unconditionally, after including > > > complex.h and #undef'ing CMPLX[FL], since musl does not require a C11 > > > compiler to build it. Depending on whether a fallback is provided for > > > old compilers or not, I think your approach could lead to musl being > > > miscompiled. It probably doesn't happen since CMPLX is no longer > > > exposed except in C11 mode, and musl is compiled with -std=c99, but > > > this looks fragile and could cause breakage to go unnoticed if we > > > switch to preferring -std=c11 some time later. (There's been talk of > > > preferring -std=c11 if it works.) > > > > Hm, clearly not my preference. I think we should use the right tool > > (which is __builtin_complex for gcc or the bogus initializer for > > clang) as soon as we have it. > > > > This is why I wanted to have the detection of the features as early as > > possible where it belongs to my opinion, complex.h. > > > > They have more chances to optimize things correctly without > > temporaries even when compiled without optimization. > > As stated in another thread, my preference is highly towards not > having multiple versions of the same code, especially when one or more > are unlikely to get good testing. The "more chance to optimize" > argument does not apply unless there really are compilers which > compile the unions poorly (not counting intentional non-optimizing > modes) and I'm not aware of any. ok, I'll prepare a new version according to that Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-02 22:00 ` Jens Gustedt @ 2014-12-02 22:47 ` Rich Felker 2014-12-03 9:18 ` Jens Gustedt 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2014-12-02 22:47 UTC (permalink / raw) To: Jens Gustedt; +Cc: musl On Tue, Dec 02, 2014 at 11:00:12PM +0100, Jens Gustedt wrote: > Am Dienstag, den 02.12.2014, 14:42 -0500 schrieb Rich Felker: > > On Tue, Dec 02, 2014 at 08:10:32PM +0100, Jens Gustedt wrote: > > > > Does clang not support the GCC builtin? > > > > > > no, and I don't have the impression they will. They invented their own > > > internals for this, as you can see here. > > > > Yes, but their form is a bug that needs to be removed, so they'll have > > to add something in its place, and __builtin_complex is the natural > > choice. For what it's worth, glibc only supports __builtin_complex and > > just does not define these macros at all if it's not supported. > > you mean it is a bug because the two-value-initializer is a constraint > violation? It only is a bug that has to be diagnosed if user code is > using it. Internals as long they are not visible to the user isn't > covered by this, I think. And this is exactly the reason why the > macros have been introduced in C11, to hide such cruft from the user's > eye :) Well, maybe, if they handle it via warning suppression in the system header path. But this seems fragile. > > > > My preference would be if we could just define CMPLX either in terms > > > > of __builtin_complex, > > > > > > not possible, I think > > > > Well, it's what glibc does. That's not to say it's a good choice, but > > it suggests there could be pressure to get other compilers to support > > it. > > and that's then one of the points where they aren't C11 conforming > when compiled with other compilers Then what about something like #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx // use clang compound literal hack #elif __GNUC__*100+__GNUC_MINOR__ >= 407 // use __builtin_complex #else // use _Complex_I with mult and add #endif or alternatively: #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx // use clang compound literal hack #else // use __builtin_complex #endif I somewhat prefer the latter since the _Complex_I form is never really correct (INF/NAN issues) and it gives better fallback behavior assuming other compilers will implement __builtin_complex but might not identify themselves as "GNU C >= 4.7". It also produces an error on compilers that can't give the right behavior for INF/NAN rather than silently miscompiling the code. > > > > _Imaginary_I > > > > is not supported yet at all and would require further changes to this > > > > header to add anyway (this header is responsible for defining it), so > > > > conditioning on its definition is not meaningful. > > > > > > I am not sure of that. It could also come directly from the compiler > > > just as it defines some __SOMETHING__ macros before any include > > > > I don't think so. Consider: > > > > #undef _Imaginary_I > > #include <complex.h> > > > > Perhaps this is non-conforming for technical reasons, > > it is non-conforming Because of the _-prefixed namespace? Per my understanding, it's conforming to #undef macros provided by the standard headers in many cases. Eliminating a function-like macro to get at the underlying function is one such usage mentioned in the standard, but I think there are others too. > > but the standard > > is fairly direct in saying that complex.h defines the _Imaginary_I > > macro rather than just having it predefined. > > but it also says > > » Implementations that define the macro __STDC_NO_COMPLEX__ need not provide > » this header nor support any of its facilities. > > so any of the facilities *may* be provided anyhow. (and since > _Imaginary_I is reserved it is allowed to do that in any case.) > > But if you want to avoid that branch, I understand. _Imaginary_I would > be *the* way to solve all of this easily, sigh. Yes, I really wish GCC would support it, especially since Annex G _requires_ _Imaginary_I, and glibc falsely advertises Annex G support via the __STDC_IEC_559_COMPLEX__ macro despite not having _Imaginary_I. But the glibc folks seem to think this is a non-issue and I haven't seen any interest in fixing it on the GCC side. Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-02 22:47 ` Rich Felker @ 2014-12-03 9:18 ` Jens Gustedt 2014-12-03 14:38 ` Rich Felker 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-12-03 9:18 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 4154 bytes --] Hello, Am Dienstag, den 02.12.2014, 17:47 -0500 schrieb Rich Felker: > On Tue, Dec 02, 2014 at 11:00:12PM +0100, Jens Gustedt wrote: > Then what about something like > > #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx > // use clang compound literal hack > #elif __GNUC__*100+__GNUC_MINOR__ >= 407 > // use __builtin_complex > #else > // use _Complex_I with mult and add > #endif > > or alternatively: > > #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx > // use clang compound literal hack > #else > // use __builtin_complex > #endif > > I somewhat prefer the latter since the _Complex_I form is never really > correct (INF/NAN issues) and it gives better fallback behavior > assuming other compilers will implement __builtin_complex but might > not identify themselves as "GNU C >= 4.7". It also produces an error > on compilers that can't give the right behavior for INF/NAN rather > than silently miscompiling the code. I agree with your analysis, we should avoid using _Complex_I, here. For the implementation I don't agree completely. Version number games are not the right thing for clang, they don't support this, in a sense in the same way that you don't want a macro that identifies musl. They have their feature/builtin test framework, we should use that. This then would kick in whenever they decide to implement that builtin. But still, I'd like to have a version with _Imaginary_I, see below. > > > > > _Imaginary_I > > > > > is not supported yet at all and would require further changes to this > > > > > header to add anyway (this header is responsible for defining it), so > > > > > conditioning on its definition is not meaningful. > > > > > > > > I am not sure of that. It could also come directly from the compiler > > > > just as it defines some __SOMETHING__ macros before any include > > > > > > I don't think so. Consider: > > > > > > #undef _Imaginary_I > > > #include <complex.h> > > > > > > Perhaps this is non-conforming for technical reasons, > > > > it is non-conforming > > Because of the _-prefixed namespace? Yes, an implementation simply *mustn't* touch any identifier that starts with underscore and capital letter. Period. > Per my understanding, it's > conforming to #undef macros provided by the standard headers in many > cases. > Eliminating a function-like macro to get at the underlying > function is one such usage mentioned in the standard, but I think > there are others too. I don't know of many, and these are explicitly named. And all of this is *not* the same thing as the case above. This concerns e.g "complex" and "I" which are otherwise not reserved, and not e.g "_Complex_I" that falls under the same rule as _Imaginary_I. > > But if you want to avoid that branch, I understand. _Imaginary_I would > > be *the* way to solve all of this easily, sigh. > > Yes, I really wish GCC would support it, especially since Annex G > _requires_ _Imaginary_I, and glibc falsely advertises Annex G support > via the __STDC_IEC_559_COMPLEX__ macro despite not having > _Imaginary_I. But the glibc folks seem to think this is a non-issue > and I haven't seen any interest in fixing it on the GCC side. argh, I wasn't aware of that, what a mess. yes _Imaginary and all that comes with it is really an important feature of that Annex, e.g functions returning _Imaginary values when known to have such values. So I keep my claim for a first case version with _Imaginary_I up :) we should encourage compiler implementors to provide this feature. I looked a bit around and I found that - Keil supports imaginary - for Cray compilers 1.0i is pure imaginary and not complex, but they don't explain exactly what happens if you use this in arithmetic Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-03 9:18 ` Jens Gustedt @ 2014-12-03 14:38 ` Rich Felker 2014-12-03 15:12 ` Jens Gustedt 0 siblings, 1 reply; 16+ messages in thread From: Rich Felker @ 2014-12-03 14:38 UTC (permalink / raw) To: musl On Wed, Dec 03, 2014 at 10:18:31AM +0100, Jens Gustedt wrote: > Hello, > > Am Dienstag, den 02.12.2014, 17:47 -0500 schrieb Rich Felker: > > On Tue, Dec 02, 2014 at 11:00:12PM +0100, Jens Gustedt wrote: > > Then what about something like > > > > #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx > > // use clang compound literal hack > > #elif __GNUC__*100+__GNUC_MINOR__ >= 407 > > // use __builtin_complex > > #else > > // use _Complex_I with mult and add > > #endif > > > > or alternatively: > > > > #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx > > // use clang compound literal hack > > #else > > // use __builtin_complex > > #endif > > > > I somewhat prefer the latter since the _Complex_I form is never really > > correct (INF/NAN issues) and it gives better fallback behavior > > assuming other compilers will implement __builtin_complex but might > > not identify themselves as "GNU C >= 4.7". It also produces an error > > on compilers that can't give the right behavior for INF/NAN rather > > than silently miscompiling the code. > > I agree with your analysis, we should avoid using _Complex_I, here. > > For the implementation I don't agree completely. Version number games > are not the right thing for clang, they don't support this, in a sense > in the same way that you don't want a macro that identifies musl. OK. I had it commented just as a suggestion that we could do some detection for clang versions that need the clang-specific compound literal hack if/when there are versions that no longer need it. In any case right now it would just be #ifdef __clang__ I think. > But still, I'd like to have a version with _Imaginary_I, see below. I'd like to have it in mind for the future, but putting it in the file is confusing since it can't be used without further changes to the file. > > > > > > _Imaginary_I > > > > > > is not supported yet at all and would require further changes to this > > > > > > header to add anyway (this header is responsible for defining it), so > > > > > > conditioning on its definition is not meaningful. > > > > > > > > > > I am not sure of that. It could also come directly from the compiler > > > > > just as it defines some __SOMETHING__ macros before any include > > > > > > > > I don't think so. Consider: > > > > > > > > #undef _Imaginary_I > > > > #include <complex.h> > > > > > > > > Perhaps this is non-conforming for technical reasons, > > > > > > it is non-conforming > > > > Because of the _-prefixed namespace? > > Yes, an implementation simply *mustn't* touch any identifier that > starts with underscore and capital letter. Period. Or other reserved identifiers? I think you're just saying things that you're explicitly allowed to #undef are special, and otherwise reserved identifiers are not admissible for #undef. In any case this isn't a really important matter. > > > But if you want to avoid that branch, I understand. _Imaginary_I would > > > be *the* way to solve all of this easily, sigh. > > > > Yes, I really wish GCC would support it, especially since Annex G > > _requires_ _Imaginary_I, and glibc falsely advertises Annex G support > > via the __STDC_IEC_559_COMPLEX__ macro despite not having > > _Imaginary_I. But the glibc folks seem to think this is a non-issue > > and I haven't seen any interest in fixing it on the GCC side. > > argh, I wasn't aware of that, what a mess. yes _Imaginary and all that > comes with it is really an important feature of that Annex, e.g > functions returning _Imaginary values when known to have such values. > > So I keep my claim for a first case version with _Imaginary_I up :) > we should encourage compiler implementors to provide this feature. > > I looked a bit around and I found that > - Keil supports imaginary > - for Cray compilers 1.0i is pure imaginary and not complex, but they > don't explain exactly what happens if you use this in arithmetic Perhaps we should redefine _Complex_I as (0.0f+1.0fi) so that it's clearly complex even if the compiler has 1.0fi as a pure-imaginary type. Rich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-12-03 14:38 ` Rich Felker @ 2014-12-03 15:12 ` Jens Gustedt 0 siblings, 0 replies; 16+ messages in thread From: Jens Gustedt @ 2014-12-03 15:12 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 5127 bytes --] Hi, Am Mittwoch, den 03.12.2014, 09:38 -0500 schrieb Rich Felker: > On Wed, Dec 03, 2014 at 10:18:31AM +0100, Jens Gustedt wrote: > > > #if __clang__ // && __clang_major__*100+__clang_minor__ <= xxxxx > > > // use clang compound literal hack > > > #else > > > // use __builtin_complex > > > #endif > > > > > > I somewhat prefer the latter since the _Complex_I form is never really > > > correct (INF/NAN issues) and it gives better fallback behavior > > > assuming other compilers will implement __builtin_complex but might > > > not identify themselves as "GNU C >= 4.7". It also produces an error > > > on compilers that can't give the right behavior for INF/NAN rather > > > than silently miscompiling the code. > > > > I agree with your analysis, we should avoid using _Complex_I, here. > > > > For the implementation I don't agree completely. Version number games > > are not the right thing for clang, they don't support this, in a sense > > in the same way that you don't want a macro that identifies musl. > > OK. I had it commented just as a suggestion that we could do some > detection for clang versions that need the clang-specific compound > literal hack if/when there are versions that no longer need it. In any > case right now it would just be #ifdef __clang__ I think. so you want to see this changed explicitly, the day they support this? on that day the correct version will most certainly look like #ifndef __has_builtin #define __has_builtin(x) 0 // Compatibility with non-clang compilers. #endif #if __clang__ && !__has_builtin(__builtin_complex) // use clang compound literal hack #else // use __builtin_complex #endif so we could have that from the start and not talk about it anymore :) > > But still, I'd like to have a version with _Imaginary_I, see below. > > I'd like to have it in mind for the future, but putting it in the file > is confusing since it can't be used without further changes to the > file. > > > > > > > > _Imaginary_I > > > > > > > is not supported yet at all and would require further changes to this > > > > > > > header to add anyway (this header is responsible for defining it), so > > > > > > > conditioning on its definition is not meaningful. > > > > > > > > > > > > I am not sure of that. It could also come directly from the compiler > > > > > > just as it defines some __SOMETHING__ macros before any include > > > > > > > > > > I don't think so. Consider: > > > > > > > > > > #undef _Imaginary_I > > > > > #include <complex.h> > > > > > > > > > > Perhaps this is non-conforming for technical reasons, > > > > > > > > it is non-conforming > > > > > > Because of the _-prefixed namespace? > > > > Yes, an implementation simply *mustn't* touch any identifier that > > starts with underscore and capital letter. Period. > > Or other reserved identifiers? I think you're just saying things that > you're explicitly allowed to #undef are special, and otherwise > reserved identifiers are not admissible for #undef. most reserved identifiers are only so, provided you include this or that header, e.g bool, false and true. The _Something identifiers are always reserved, they are reserved for language specific features, not library. > In any case this isn't a really important matter. agreed > > > > But if you want to avoid that branch, I understand. _Imaginary_I would > > > > be *the* way to solve all of this easily, sigh. > > > > > > Yes, I really wish GCC would support it, especially since Annex G > > > _requires_ _Imaginary_I, and glibc falsely advertises Annex G support > > > via the __STDC_IEC_559_COMPLEX__ macro despite not having > > > _Imaginary_I. But the glibc folks seem to think this is a non-issue > > > and I haven't seen any interest in fixing it on the GCC side. > > > > argh, I wasn't aware of that, what a mess. yes _Imaginary and all that > > comes with it is really an important feature of that Annex, e.g > > functions returning _Imaginary values when known to have such values. > > > > So I keep my claim for a first case version with _Imaginary_I up :) > > we should encourage compiler implementors to provide this feature. > > > > I looked a bit around and I found that > > - Keil supports imaginary > > - for Cray compilers 1.0i is pure imaginary and not complex, but they > > don't explain exactly what happens if you use this in arithmetic > > Perhaps we should redefine _Complex_I as (0.0f+1.0fi) so that it's > clearly complex even if the compiler has 1.0fi as a pure-imaginary > type. yes, good idea, also it makes it explicit for the eye that this is a complex value. For me, having a heavily biased math background, reading 0.0i as complex is still counterintuitive. Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables @ 2014-11-25 14:49 Jens Gustedt 2014-11-25 15:25 ` Szabolcs Nagy 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-11-25 14:49 UTC (permalink / raw) To: musl --- include/complex.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/complex.h b/include/complex.h index 13a45c5..3e14e04 100644 --- a/include/complex.h +++ b/include/complex.h @@ -112,8 +112,7 @@ 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) +#define __CMPLX(x, y, t) ((t)(x) + _Complex_I*(t)(y)) #define CMPLX(x, y) __CMPLX(x, y, double) #define CMPLXF(x, y) __CMPLX(x, y, float) -- 1.9.1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 14:49 Jens Gustedt @ 2014-11-25 15:25 ` Szabolcs Nagy 2014-11-25 19:21 ` Szabolcs Nagy 2014-11-25 20:08 ` Jens Gustedt 0 siblings, 2 replies; 16+ messages in thread From: Szabolcs Nagy @ 2014-11-25 15:25 UTC (permalink / raw) To: musl * Jens Gustedt <Jens.Gustedt@inria.fr> [2014-11-25 15:49:39 +0100]: > diff --git a/include/complex.h b/include/complex.h > index 13a45c5..3e14e04 100644 > --- a/include/complex.h > +++ b/include/complex.h > @@ -112,8 +112,7 @@ 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) hm the compound literal is not a constant expression that is sad > +#define __CMPLX(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > this is only correct if the compiler supports annex g kind of imaginary type, otherwise it is incorrect for infinites _Complex_I*INFINITY == (0 + i)*(inf + i*0) == nan + i*inf so imaginary inf will turn into nan real part this is what gcc (and i assume clang) does > #define CMPLX(x, y) __CMPLX(x, y, double) > #define CMPLXF(x, y) __CMPLX(x, y, float) > -- > 1.9.1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 15:25 ` Szabolcs Nagy @ 2014-11-25 19:21 ` Szabolcs Nagy 2014-11-25 21:23 ` Jens Gustedt 2014-11-25 20:08 ` Jens Gustedt 1 sibling, 1 reply; 16+ messages in thread From: Szabolcs Nagy @ 2014-11-25 19:21 UTC (permalink / raw) To: musl * Szabolcs Nagy <nsz@port70.net> [2014-11-25 16:25:00 +0100]: > * Jens Gustedt <Jens.Gustedt@inria.fr> [2014-11-25 15:49:39 +0100]: > > -#define __CMPLX(x, y, t) \ > > - ((union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z) > > hm the compound literal is not a constant expression > > > +#define __CMPLX(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > > > > this is only correct if the compiler supports annex g kind of > imaginary type, otherwise it is incorrect for infinites it seems gcc added __builtin_complex but there is no easy way to check for the availability of such builtin (other than checking >= gcc 4.7) http://gcc.gnu.org/ml/gcc-patches/2011-08/msg01600.html i guess we could use the builtin with gcc version check and fall back to the compound literal version otherwise (it wont work as static initializer then, but right now the biggest user of CMPLX is most likely musl src/complex/* which dont need it to be constant expr but does rely on proper semantics for infinites and signed zeros) ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 19:21 ` Szabolcs Nagy @ 2014-11-25 21:23 ` Jens Gustedt 2014-11-25 23:19 ` Szabolcs Nagy 0 siblings, 1 reply; 16+ messages in thread From: Jens Gustedt @ 2014-11-25 21:23 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 1489 bytes --] Am Dienstag, den 25.11.2014, 20:21 +0100 schrieb Szabolcs Nagy: > it seems gcc added __builtin_complex but there is no easy way to check > for the availability of such builtin (other than checking >= gcc 4.7) Haven't they planned to implement a feature test tool, similar to clang's ? Basically this means that we only can use it in C11 mode, I guess. At least that one has a feature test macro :) > i guess we could use the builtin with gcc version check This always has the possibility of false detection when using one of the other compilers that simulate gcc behavior. Usually getting this right for all such compilers is quite a pain. I'll see what clang offers, here. > and fall back > to the compound literal version otherwise (it wont work as static > initializer then, but right now the biggest user of CMPLX is most > likely musl src/complex/* which dont need it to be constant expr > but does rely on proper semantics for infinites and signed zeros) If that is so, I'd be in favor of having and using an internal macro that uses the compound literal. The compilation of the library shouldn't depend too much on compiler versions. Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 21:23 ` Jens Gustedt @ 2014-11-25 23:19 ` Szabolcs Nagy 2014-11-26 7:45 ` Jens Gustedt 0 siblings, 1 reply; 16+ messages in thread From: Szabolcs Nagy @ 2014-11-25 23:19 UTC (permalink / raw) To: musl * Jens Gustedt <jens.gustedt@inria.fr> [2014-11-25 22:23:03 +0100]: > right for all such compilers is quite a pain. I'll see what clang > offers, here. > clang has static double _Complex z = (double _Complex){x, y}; which is problematic because it is a language extension that gcc and other c11 compilers wont support most likely (a compound literal (T){x,y} is a constraint violation for scalar T, so a sensible c11 compiler will emit diagnostics) > > and fall back > > to the compound literal version otherwise (it wont work as static > > initializer then, but right now the biggest user of CMPLX is most > > likely musl src/complex/* which dont need it to be constant expr > > but does rely on proper semantics for infinites and signed zeros) > > If that is so, I'd be in favor of having and using an internal macro > that uses the compound literal. The compilation of the library > shouldn't depend too much on compiler versions. > it used to be an internal macro, but i thought it makes sense to use the new CMPLX instead when it was added to complex.h but if CMPLX semantics cannot be guaranteed with c99 features then probably we should go back to the internal macro (and not define CMPLX at all in complex.h if the semantics is wrong) ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 23:19 ` Szabolcs Nagy @ 2014-11-26 7:45 ` Jens Gustedt 0 siblings, 0 replies; 16+ messages in thread From: Jens Gustedt @ 2014-11-26 7:45 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 3294 bytes --] Hello, Am Mittwoch, den 26.11.2014, 00:19 +0100 schrieb Szabolcs Nagy: > * Jens Gustedt <jens.gustedt@inria.fr> [2014-11-25 22:23:03 +0100]: > > right for all such compilers is quite a pain. I'll see what clang > > offers, here. > > > > clang has > > static double _Complex z = (double _Complex){x, y}; yes, I noticed that in the mean time, too > which is problematic because it is a language extension that > gcc and other c11 compilers wont support most likely we'd have to do case analysis according to the compiler, anyhow, since there will be some time that other compilers implement __builtin_complex, or which would even be better, _Imaginary. > (a compound literal (T){x,y} is a constraint violation for > scalar T, so a sensible c11 compiler will emit diagnostics) > > > > and fall back > > > to the compound literal version otherwise (it wont work as static > > > initializer then, but right now the biggest user of CMPLX is most > > > likely musl src/complex/* which dont need it to be constant expr > > > but does rely on proper semantics for infinites and signed zeros) > > > > If that is so, I'd be in favor of having and using an internal macro > > that uses the compound literal. The compilation of the library > > shouldn't depend too much on compiler versions. > > > > it used to be an internal macro, but i thought it makes sense > to use the new CMPLX instead when it was added to complex.h > > but if CMPLX semantics cannot be guaranteed with c99 features I suppose that these were added to the standard, because such a feature needs compiler extensions > then probably we should go back to the internal macro (and not > define CMPLX at all in complex.h if the semantics is wrong) I would much be in favor of that, we shouldn't put the quality of the library implementation in danger just because of some border cases for this macro. So I prepare a patch in that sense? Below you see what I have currently, but I don't like it at all. Jens #define __CMPLX_NC(x, y, t) (+(union { _Complex t __z; t __xy[2]; }){.__xy = {(x),(y)}}.__z) #if defined(_Imaginary_I) # define __CMPLX_I(x, y, t) ((t)(x) + _Imaginary_I*(t)(y)) #else # define __CMPLX_I(x, y, t) ((t)(x) + _Complex_I*(t)(y)) #endif #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 defined(__GNUC__) # if (__STDC_VERSION__ >= 201112L) # define __CMPLX(x, y, t) __builtin_complex((t)(x), (t)(y)) # elif (__GNUC__ >= 3) # define __CMPLX(x, y, t) \ (__builtin_constant_p(x+y) ? __CMPLX_I(x, y, t) : __CMPLX_NC(x, y, t)) # endif #endif #ifndef __CMPLX # define __CMPLX(x, y, t) __CMPLX_I(x, y, t) #endif #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) -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables 2014-11-25 15:25 ` Szabolcs Nagy 2014-11-25 19:21 ` Szabolcs Nagy @ 2014-11-25 20:08 ` Jens Gustedt 1 sibling, 0 replies; 16+ messages in thread From: Jens Gustedt @ 2014-11-25 20:08 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 1322 bytes --] Am Dienstag, den 25.11.2014, 16:25 +0100 schrieb Szabolcs Nagy: > * Jens Gustedt <Jens.Gustedt@inria.fr> [2014-11-25 15:49:39 +0100]: > > +#define __CMPLX(x, y, t) ((t)(x) + _Complex_I*(t)(y)) > > > > this is only correct if the compiler supports annex g kind of > imaginary type, otherwise it is incorrect for infinites even then it would only work by using _Imaginary_I, I think > _Complex_I*INFINITY == (0 + i)*(inf + i*0) == nan + i*inf > > so imaginary inf will turn into nan real part right (but I think it is more import to get initialization of normal complex constants going, than the border cases with INFINITY and NAN) to support this it seems that gcc provides __builtin_complex, so we could implement this subject to some case analysis according to __builtin_const etc. But since the doc for __builtin_complex explicitly mentions C11, this probably doesn't exist for older versions of gcc. I'll think of it and prepare a new version of this patch Thanks Jens -- :: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-12-03 15:12 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-11-26 13:07 [PATCH 1/4] the CMPLX macros must be usable in initializations of static variables Jens Gustedt 2014-12-02 17:49 ` Rich Felker 2014-12-02 19:10 ` Jens Gustedt 2014-12-02 19:42 ` Rich Felker 2014-12-02 22:00 ` Jens Gustedt 2014-12-02 22:47 ` Rich Felker 2014-12-03 9:18 ` Jens Gustedt 2014-12-03 14:38 ` Rich Felker 2014-12-03 15:12 ` Jens Gustedt -- strict thread matches above, loose matches on Subject: below -- 2014-11-25 14:49 Jens Gustedt 2014-11-25 15:25 ` Szabolcs Nagy 2014-11-25 19:21 ` Szabolcs Nagy 2014-11-25 21:23 ` Jens Gustedt 2014-11-25 23:19 ` Szabolcs Nagy 2014-11-26 7:45 ` Jens Gustedt 2014-11-25 20:08 ` Jens Gustedt
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).