Author Topic: gcc v8-v10, undefined reference to `CMPLX': what to do?  (Read 11232 times)

0 Members and 4 Guests are viewing this topic.

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
gcc v8-v10, undefined reference to `CMPLX': what to do?
« on: February 24, 2022, 02:50:10 pm »
it looks like making sure the macro is defined is not up to GCC, and it sounds like the { compiler{gcc-v8, gcc-v9, gcc-v10} , platform{linux/x86-32bit, linux/mips32r2be-32bit, linux/ppc32be-32bit, linux/ppc64be-32bit} combination doesn't support it.
Code: [Select]
- compiling complex ... complex.c: In function 'hh2':
complex.c:72:12: warning: implicit declaration of function 'CMPLX' [-Wimplicit-function-declaration]
   72 |     cplx = CMPLX(real, imag);
      |            ^~~~~
complex.c:74:44: warning: implicit declaration of function 'cargf' [-Wimplicit-function-declaration]
   74 |     printf("Phase Angle = %.1f radians\n", cargf(cplx));
      |                                            ^~~~~
complex.c:74:44: warning: incompatible implicit declaration of built-in function 'cargf'
complex.c:11:1: note: include '<complex.h>' or provide a declaration of 'cargf'
   10 | #include <stdio.h>
  +++ |+#include <complex.h>
   11 |

But that's really weird  :-//

Code: [Select]
-std=c99 -Wall -Wextra
Code: [Select]
-std=c11 -Wall -Wextra
Tried c99/c11, same result.


Code: [Select]
#include <complex.h>
#include <tgmath.h>
#include <math.h>
#include <stdio.h>

typedef _Complex float       zf_t;
typedef _Complex double      zd_t;
typedef _Complex long double zld_t;

void hh2()
{
    double real;
    double imag;
    zd_t   cplx;

    real = 1.3;
    imag = 4.9;
    cplx = CMPLX(real, imag);

    printf("Phase Angle = %.1f radians\n", cargf(cplx));
}
...
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 3034
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #1 on: February 24, 2022, 03:16:31 pm »
Native or cross compile?

It works on my Fedora 34 box with -m32 producing a valid i686 binary.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #2 on: February 24, 2022, 04:19:36 pm »
Native or cross compile?

Native on all the mentioned platforms.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 8349
  • Country: fi
    • My home page and email address
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #3 on: February 24, 2022, 05:20:09 pm »
Which C library and C library version?

CMPLX() is C11, not C99, so use -std=c11 only.

Try including <math.h> before <complex.h>.  Because of the interdependencies, that might matter even though it shouldn't.
 
The following users thanked this post: newbrain

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 3034
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #4 on: February 24, 2022, 05:46:30 pm »
Which C library and C library version?
Which Linux distribution as well, there are not many that are natively 32 bit any longer, at least on Intel.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #5 on: February 24, 2022, 06:22:39 pm »
Which C library and C library version?

/usr/lib/libc.{a,so} -> glibc
/usr/lib/libm.{a,so} -> glibc

glibc-v2.32-r5
libtool-v2.4.6-r6 (just recompiled)

I rebuilt libtool, and gcc-v10 with the last patch-set

CMPLX() is C11, not C99, so use -std=c11 only.

ok

Try including <math.h> before <complex.h>.  Because of the interdependencies, that might matter even though it shouldn't.

I commented "tgmath" because it causes some issues

Code: [Select]
#include <math.h>
#include <complex.h>
//#include <tgmath.h>
#include <stdio.h>

now Gcc-v10 compiles, even if ...

Code: [Select]
sizeof(_Complex float)       =  8
sizeof(_Complex double)      = 16
sizeof(_Complex long double) = 24
I = 0.0+1.0i
I * I = -1.0+0.0i
pow(I, 0) = 1.0+0.0i
pow(I, 1) = 0.0+0.0i
pow(I, 2) = 0.0+0.0i
pow(I, 3) = 0.0+0.0i
exp(I*PI) = 1.0+0.0i
(1+2i)*(1-2i) = 5.0+0.0i
Phase Angle = 1.3 radians
(tested on Linux/x86-32bit)

It seems something is bad: pow(I,2) shouldn't be zero  :-//

Code: [Select]
typedef _Complex float         zf_t;
typedef _Complex double        zd_t;
typedef _Complex long double   zld_t;

void hh1()
{
    zd_t z1;
    zd_t z2;
    zd_t z3;
    zd_t z4;
    zd_t z5;
    double PI;

    z1 = I;     // imaginary unit
    printf("I = %.1f%+.1fi\n", creal(z1), cimag(z1));

    z1 = I * I;     // imaginary unit squared
    printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1));

    z2 = 1 * I;
    z2 = pow(z2, 0);
    printf("pow(I, 0) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 1);
    printf("pow(I, 1) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 2); // imaginary unit squared
    printf("pow(I, 2) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 3);
    printf("pow(I, 3) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    PI = acos(-1);

    z3 = exp(I * PI); // Euler's formula
    printf("exp(I*PI) = %.1f%+.1fi\n", creal(z3), cimag(z3));

    z4 = 1+2*I;
    z5 = 1-2*I; // conjugates
    printf("(1+2i)*(1-2i) = %.1f%+.1fi\n", creal(z4*z5), cimag(z4*z5));
}

edit:
So, there was something wrong with libtool! You have to be careful when you cook gcc >=v10
« Last Edit: February 24, 2022, 07:46:20 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #6 on: February 24, 2022, 06:26:22 pm »
pow(I, 0) = 1.0+0.0i: correct
pow(I, 1) = 0.0+0.0i: wrong
pow(I, 2) = 0.0+0.0i: wrong
pow(I, 3) = 0.0+0.0i: wrong



with
Code: [Select]
#include <math.h>
#include <complex.h>
#include <tgmath.h> // do I have to comment this?!?
#include <stdio.h>
there is this issue
Code: [Select]
- compiling cplx ... In file included from cplx.c:9:
cplx.c: In function 'hh1':
cplx.c:55:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   55 |     z2 = pow(z2, 0);
      |          ^~~
cplx.c:59:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   59 |     z2 = pow(z2, 1);
      |          ^~~
cplx.c:63:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   63 |     z2 = pow(z2, 2); // imaginary unit squared
      |          ^~~
cplx.c:67:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   67 |     z2 = pow(z2, 3);
      |          ^~~
cplx.c:70:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   70 |     PI = acos(-1);
      |          ^~~~
cplx.c:72:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   72 |     z3 = exp(I * PI); // Euler's formula
      |          ^~~
make: *** [Makefile:77: obj/macmini-intel-i686/cplx.o] Error 1
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #7 on: February 24, 2022, 06:30:59 pm »
Which Linux distribution as well, there are not many that are natively 32 bit any longer, at least on Intel.

Gentoo/Catalyst, so they are autobuilt stage0-4
I am going to also build for ARM(1)-64bit and HPPA2-32bit

(1) ARMv7-gnueabihf (hardware fp)
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17787
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #8 on: February 24, 2022, 06:33:38 pm »
Yes, this macro appeared in C11, it was not defined in C99, so that's the minimum revision you need to use.

With that said - I tried with the latest GCC (11.2), and the macro is indeed not supported. Even with std=c2x.

So out of curiosity, I did a search in all header files from all GCC compilers I have on my workstation, with a variety of versions. None have the 'CMPLX' macro defined in any of their header files.

I have no explanation for this, apart from just a missing macro in GCC's complex.h. Didn't check for Clang yet. Reading the standard (both C11 and the draft of C2x), there is no mention of it being possibly optional.

Note that the suggested way of achieving the same (while actually being more readable IMHO, since closer to math notation) before this macro appeared was to use the 'I' macro from complex.h (which is normally defined as '_Complex_I'), such as:
Code: [Select]
double complex x = 1 + 2*I;which I tend to prefer anyway.
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 3034
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #9 on: February 24, 2022, 06:39:59 pm »
With that said - I tried with the latest GCC (11.2), and the macro is indeed not supported. Even with std=c2x.
complex.h is part of glibc, rather than GCC.
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 8061
  • Country: pl
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #10 on: February 24, 2022, 06:45:15 pm »
Works for me :-//
Code: [Select]
$ grep -C2 CMPLX /usr/include/complex.h
#if defined __USE_ISOC11 && __GNUC_PREREQ (4, 7)
/* Macros to expand into expression of specified complex type.  */
# define CMPLX(x, y) __builtin_complex ((double) (x), (double) (y))
# define CMPLXF(x, y) __builtin_complex ((float) (x), (float) (y))
# define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y))
#endif

#if __HAVE_FLOAT16 && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF16(x, y) __builtin_complex ((_Float16) (x), (_Float16) (y))
#endif

#if __HAVE_FLOAT32 && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF32(x, y) __builtin_complex ((_Float32) (x), (_Float32) (y))
#endif

#if __HAVE_FLOAT64 && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF64(x, y) __builtin_complex ((_Float64) (x), (_Float64) (y))
#endif

#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF128(x, y) __builtin_complex ((_Float128) (x), (_Float128) (y))
#endif

#if __HAVE_FLOAT32X && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF32X(x, y) __builtin_complex ((_Float32x) (x), (_Float32x) (y))
#endif

#if __HAVE_FLOAT64X && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF64X(x, y) __builtin_complex ((_Float64x) (x), (_Float64x) (y))
#endif

#if __HAVE_FLOAT128X && __GLIBC_USE (IEC_60559_TYPES_EXT)
# define CMPLXF128X(x, y)                                       \
  __builtin_complex ((_Float128x) (x), (_Float128x) (y))
#endif
I suppose you could use __builtin_complex as a substitute :-DD

With that said - I tried with the latest GCC (11.2), and the macro is indeed not supported. Even with std=c2x.
complex.h is part of glibc, rather than GCC.
Yep, that's the case on my system too.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1908
  • Country: se
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #11 on: February 24, 2022, 08:19:51 pm »
pow(I, 0) = 1.0+0.0i: correct
pow(I, 1) = 0.0+0.0i: wrong
pow(I, 2) = 0.0+0.0i: wrong
pow(I, 3) = 0.0+0.0i: wrong
If <tgmath.h> is not included the above results are exactly what expected, a _Complex value converted to regular float or double simple loses the imaginary part - so 0 is what the (double) pow() sees.

Along NominalAnimal lines, I would suggest to try including only <tgmath.h>: it already includes both <math.h> and <complex.h>.
Correctly written includes should be idempotent, but the matter here is complex...

EtA: tgmath.h defines the type generic math library functions and macros - a basic form of overloading that can now (>=C11) be written in standard C using _Generic.
So, complex.h will contain the complex specific stuff and math.h the real specific ones.
With tgmath.h generic pow calls will be replaced with the right one (powf, pow, powl, cpowf, cpow, cpowl) according to the arguments.
« Last Edit: February 24, 2022, 08:32:19 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #12 on: February 24, 2022, 09:27:14 pm »
Along NominalAnimal lines, I would suggest to try including only <tgmath.h>: it already includes both <math.h> and <complex.h>.

Code: [Select]
//#include <math.h>
//#include <complex.h>
#include <tgmath.h>
#include <stdio.h>

typedef _Complex float         zf_t;
typedef _Complex double        zd_t;
typedef _Complex long double   zld_t;

void hh1()
{
    zd_t z1;
    zd_t z2;
    zd_t z3;
    zd_t z4;
    zd_t z5;
    double PI;

    z1 = I;     // imaginary unit
    printf("I = %.1f%+.1fi\n", creal(z1), cimag(z1));

    z1 = I * I;     // imaginary unit squared
    printf("I * I = %.1f%+.1fi\n", creal(z1), cimag(z1));

    z2 = 1 * I;
    z2 = pow(z2, 0);
    printf("pow(I, 0) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 1);
    printf("pow(I, 1) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 2); // imaginary unit squared
    printf("pow(I, 2) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    z2 = 1 * I;
    z2 = pow(z2, 3);
    printf("pow(I, 3) = %.1f%+.1fi\n", creal(z2), cimag(z2));

    PI = acos(-1);

    z3 = exp(I * PI); // Euler's formula
    printf("exp(I*PI) = %.1f%+.1fi\n", creal(z3), cimag(z3));

    z4 = 1+2*I;
    z5 = 1-2*I; // conjugates
    printf("(1+2i)*(1-2i) = %.1f%+.1fi\n", creal(z4*z5), cimag(z4*z5));
}

Code: [Select]
- compiling cplx ... In file included from cplx.c:9:
cplx.c: In function 'hh1':
cplx.c:55:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   55 |     z2 = pow(z2, 0);
      |          ^~~
cplx.c:59:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   59 |     z2 = pow(z2, 1);
      |          ^~~
cplx.c:63:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   63 |     z2 = pow(z2, 2); // imaginary unit squared
      |          ^~~
cplx.c:67:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   67 |     z2 = pow(z2, 3);
      |          ^~~
cplx.c:70:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   70 |     PI = acos(-1);
      |          ^~~~
cplx.c:72:10: error: duplicate type-generic parameter type for function argument 2 of '__builtin_tgmath'
   72 |     z3 = exp(I * PI); // Euler's formula
      |          ^~~
make: *** [Makefile:77: obj/macmini-intel-i686/cplx.o] Error 1
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17787
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #13 on: February 24, 2022, 10:08:48 pm »
With that said - I tried with the latest GCC (11.2), and the macro is indeed not supported. Even with std=c2x.
complex.h is part of glibc, rather than GCC.

No. complex.h is part of the C std, and *is* provided by GCC.
Do not confuse particular file layouts/distributions on particular systems with what is standard C. Complex numbers are part of the C std when supported, glibc is just a particular implementation.

GCC absolutely does come with complex.h. The boggling part is why CMPLX is not defined in it, while basic support of complex numbers is. Actually, it looks like complex.h in GCC never got updated past C99 support, although I have no 100% certainty about it.

But this is certainly a bug. The std clearly states:
Quote
Implementations  that  define  the  macro __STDC_NO_COMPLEX__ need  not  provide this header* nor support any of its facilities.
*'complex.h'

On all configurations I tried (various GCC versions, various targets), this macro is NOT defined, 'complex.h' exists, but it does not define the CMPLX macro. It does define the rest of complex numbers support as far as I've seen though, at least the basic support - didn't thoroughly check whether anything in C11+ but not in C99, apart from this macro, wasn't there. There is no valid reason for that.

If complex numbers are not supported on a given platform/version/target, the '__STDC_NO_COMPLEX__ ' should just be defined, end of story. Otherwise, anything defined in the std for "Complex arithmetic" should be available. Something kinda fishy here. Looked for something related in GCC's bugzilla, but could not find anything very interesting, except a remotely related issue that apparently never got even assigned.
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 8061
  • Country: pl
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #14 on: February 24, 2022, 10:24:34 pm »
It's part of the standard library, like stdlib.h and a few others. It even makes sense.

Perhaps you are looking at some C++ headers which do appear to ship with GCC itself.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17787
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #15 on: February 24, 2022, 10:43:17 pm »
I'm used to using a number of different GCC versions for various targets, cross-compilation or native, and most of the time, those headers are part of the GCC's distribution. But digging a bit deeper, this would not be strictly a problem with GCC indeed.

For instance, if you're using GCC for ARM-Cortex M, the standard headers are usually provided by newlib.
If you're using other targets, it depends. But if you're not doing "native" compilation on Linux (or similar environment), there is often NOT a common 'include' path - each compiler has its own stuff for the std library. It may come from newlib, glibc or yet other implementations.

So it looks like the problem lies with newlib - and some other implementations - rather than with GCC itself. I confused the two as they often come as a bundle - unless again you're strictly on native Linux.

Why a number of implementations of the C srd lib, including newlib, do not define the CMPLX macro, is now the question.

But what the compiler implements, and what the std lib implements, for complex numbers, is still a bit involved. There's of course basic support for complex numbers directly in the compiler itself, not requiring the std lib, for easy to understand reasons. (Otherwise you wouldn't have access to arithmetic on complex numbers with common operators in C, for instance. C does not have operator overloading. =) )

 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #16 on: February 24, 2022, 11:06:26 pm »
collisions

gnat-gpl-v2016-r4 -> /usr/lib/gcc/i686-pc-linux-gnu/4.9.4/include/g++-v4/complex.h

gcc-v6.5.0-r2 -> /usr/lib/gcc/i686-pc-linux-gnu/6.5.0/include/g++-v6/tr1/complex.h
gcc-v6.5.0-r2 -> /usr/lib/gcc/i686-pc-linux-gnu/6.5.0/include/g++-v6/complex.h
gcc-v7.5.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/7.5.0/include/g++-v7/tr1/complex.h
gcc-v7.5.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/7.5.0/include/g++-v7/complex.h
gcc-v8.4.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/8.4.0/include/g++-v8/tr1/complex.h
gcc-v8.4.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/8.4.0/include/g++-v8/complex.h
gcc-v9.3.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/9.3.0/include/g++-v9/tr1/complex.h
gcc-v9.3.0-r1 -> /usr/lib/gcc/i686-pc-linux-gnu/9.3.0/include/g++-v9/complex.h
gcc-v10.2.0-r3 -> /usr/lib/gcc/i686-pc-linux-gnu/10.2.0/include/g++-v10/tr1/complex.h
gcc-v10.2.0-r3 -> /usr/lib/gcc/i686-pc-linux-gnu/10.2.0/include/g++-v10/complex.h

glibc-2.32-r5 -> /usr/include/complex.h

clang-v11.0.0 -> /usr/lib/clang/11.0.0/include/openmp_wrappers/complex.h
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17787
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #17 on: February 24, 2022, 11:15:08 pm »
Yes, it can become a mess if you're using common include paths (such as is usual on Linux), and compilers with their own version of the std library.
And, this particular header file (complex.h) also comes with other things like openmp... =)

In any case, I'd suggest sticking to the 'I' macro for defining complex constants, as I showed earlier. This macro is defined in complex.h on most plaforms I've tried, contrary to CMPLX.
 
The following users thanked this post: DiTBho

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1908
  • Country: se
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #18 on: February 24, 2022, 11:16:00 pm »
..did not work...
Crap. I know it's not nice to say "works for me", but it works for me!

Note that of course you need to compile as C11 to have access to CMPLX(), see below, and link with -lm.

I used exactly your code, but with int main(void) instead of hh() and with an added z0 to test CMPLX.

Code: [Select]
newbrain@MUON:~$ gcc -std=c99 -Wall -Wextra -pedantic cpx.c -o cpx -lm
cpx.c: In function ‘main’:
cpx.c:20:10: warning: implicit declaration of function ‘CMPLX’ [-Wimplicit-function-declaration]
   20 |     z0 = CMPLX(0,I);
      |          ^~~~~
cpx.c:12:10: warning: variable ‘z0’ set but not used [-Wunused-but-set-variable]
   12 |     zd_t z0;
      |          ^~
/usr/bin/ld: /tmp/ccxcDS2j.o: in function `main':
cpx.c:(.text+0x26): undefined reference to `CMPLX'
collect2: error: ld returned 1 exit statusnewbrain@MUON:~$ gcc -std=c11 -Wall -Wextra -pedantic cpx.c -o cpx -lm
cpx.c: In function ‘main’:
cpx.c:12:10: warning: variable ‘z0’ set but not used [-Wunused-but-set-variable]
   12 |     zd_t z0;
      |          ^~
newbrain@MUON:~$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

newbrain@MUON:~$ ./cpx
I = 0.0+1.0i
I * I = -1.0+0.0i
pow(I, 0) = 1.0+0.0i
pow(I, 1) = 0.0+1.0i
pow(I, 2) = -1.0+0.0i
pow(I, 3) = -0.0-1.0i
exp(I*PI) = -1.0+0.0i
(1+2i)*(1-2i) = 5.0+0.0i
newbrain@MUON:~$
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1908
  • Country: se
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #19 on: February 24, 2022, 11:23:38 pm »
On all configurations I tried (various GCC versions, various targets), this macro is NOT defined, 'complex.h' exists, but it does not define the CMPLX macro.
If you compile with -std=C11 the "macro" will magically appear, as demonstrated above.
System include files must externally behave as if they are written in C (e.g. you can undefine a macro to make sure to get to a library function), but can use any trick the compiler writers fancy. The standard just describe how they work and what they provide, not their actual code content - in theory (but here I'm not 100% sure) they could just contain a single #pragma that tells the compiler to make their definitions available.

Edit: extended a bit my ramblings, as if someone needs them...
« Last Edit: February 24, 2022, 11:27:50 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #20 on: February 24, 2022, 11:43:11 pm »
ok, some progress:
applied Gentoo Glibc Patchset 2.32-4-rc9 and rebuilt glibc-v2.32-r5 with gcc-v10.2.0

now the above code compiles, and works as expected ...
... but glibc has still some glitches :o :o :o

Code: [Select]
# make interfaces
- touching interface private
- touching interface public
- generating interface private for cplx
/usr/include/bits/mathcalls-helper-functions.h:20: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:24: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:29: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:33: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:37: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:41: syntax error at token '__x'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:44: syntax error at token '__value'
Expected: ')'
- generating interface public for cplx
/usr/include/bits/mathcalls-helper-functions.h:20: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:24: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:29: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:33: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:37: syntax error at token '__value'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:41: syntax error at token '__x'
Expected: ')'
/usr/include/bits/mathcalls-helper-functions.h:44: syntax error at token '__value'
Expected: ')'

glibc-2.32-r5 -> /usr/include/bits/mathcalls-helper-functions.h

Code: [Select]
/* Classify given number.  */
__MATHDECL_ALIAS (int, __fpclassify,, (_Mdouble_ __value), fpclassify)
     __attribute__ ((__const__));
(/usr/include/bits/mathcalls-helper-functions.h)

it doesn't understand what is "_Mdouble_"  :-//
« Last Edit: February 24, 2022, 11:48:21 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #21 on: February 24, 2022, 11:46:56 pm »
Code: [Select]
# make
- compiling cplx ... done
- linking to app

Code: [Select]
# make run
sizeof(data): 64
alignof(data): 32
sizeof(_Complex float)       =  8
sizeof(_Complex double)      = 16
sizeof(_Complex long double) = 24
I = 0.0+1.0i
I * I = -1.0+0.0i
pow(I, 0) = 1.0+0.0i
pow(I, 1) = 0.0+1.0i
pow(I, 2) = -1.0+0.0i
pow(I, 3) = -0.0-1.0i
exp(I*PI) = -1.0+0.0i
(1+2i)*(1-2i) = 5.0+0.0i
Phase Angle = 1.3 radians
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17787
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #22 on: February 24, 2022, 11:51:16 pm »
Std lib quirkiness aside, I was wondering lately whether using the complex types in C would be any more efficient than just hand-implementing complex operations with FP numbers. (Sure it's more convenient, but is it any more efficient?) Or is it even possibly less efficient? I'm curious!
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #23 on: February 25, 2022, 12:03:20 am »
Std lib quirkiness aside, I was wondering lately whether using the complex types in C would be any more efficient than just hand-implementing complex operations with FP numbers. (Sure it's more convenient, but is it any more efficient?) Or is it even possibly less efficient? I'm curious!

Considering that I have already recompiled glibc and gcc four times, I hope at least it will be more efficient  ;D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #24 on: February 25, 2022, 12:03:59 am »
/usr/include/math.h -> includes <bits/mathcalls-helper-functions.h>

Code: [Select]
#define _Mdouble_               double
#define __MATH_PRECNAME(name,r) __CONCAT(name,r)
#define __MATH_DECLARING_DOUBLE  1
#define __MATH_DECLARING_FLOATN  0
#include <bits/mathcalls-helper-functions.h>
(/usr/include/math.h)

it defines Mdoble several times
#define _Mdouble_               double
# define _Mdouble_              float
#  define _Mdouble_             long double
# define _Mdouble_              _Float16
# define _Mdouble_              _Float32
# define _Mdouble_              _Float64
# define _Mdouble_              _Float128
# define _Mdouble_              _Float32x
# define _Mdouble_              _Float64x
# define _Mdouble_              _Float128x
« Last Edit: February 25, 2022, 01:07:03 am by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf