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

0 Members and 1 Guest are viewing this topic.

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14472
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #25 on: February 25, 2022, 12:28:04 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

I admit I didn't take the time to compare this as of yet. I'll try to do that - at least look at the assembly - to get an idea.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14472
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #26 on: February 25, 2022, 01:31:09 am »
So, just made a quick comparison for just one operation: multiplication. Optimization on. GCC 11.2.0, x86_64.
Code: [Select]
double complex cmul(double complex x, double complex y)
{
        return x*y;
}

typedef struct { double Re, Im; } complex_t;

complex_t cmul2(complex_t x, complex_t y)
{
        return (complex_t){ .Re = x.Re*y.Re - x.Im*y.Im, .Im = x.Re*y.Im + x.Im*y.Re };
}

Ready for the resulting assembly?

Code: [Select]
cmul:
subq $104, %rsp
.seh_stackalloc 104
movups %xmm6, 64(%rsp)
.seh_savexmm %xmm6, 64
movups %xmm7, 80(%rsp)
.seh_savexmm %xmm7, 80
.seh_endprologue
movsd 8(%r8), %xmm4
movsd 8(%rdx), %xmm2
movsd (%r8), %xmm3
movsd (%rdx), %xmm1
movapd %xmm2, %xmm5
movapd %xmm4, %xmm0
movapd %xmm2, %xmm7
unpcklpd %xmm3, %xmm0
unpcklpd %xmm5, %xmm5
movapd %xmm3, %xmm6
mulpd %xmm0, %xmm5
movapd %xmm1, %xmm0
unpcklpd %xmm4, %xmm6
movq %rcx, %rax
mulsd %xmm3, %xmm7
unpcklpd %xmm0, %xmm0
mulpd %xmm6, %xmm0
movapd %xmm0, %xmm6
addpd %xmm5, %xmm0
subpd %xmm5, %xmm6
movapd %xmm2, %xmm5
mulsd %xmm4, %xmm5
movsd %xmm6, %xmm0
movapd %xmm1, %xmm6
mulsd %xmm3, %xmm6
subsd %xmm5, %xmm6
movapd %xmm1, %xmm5
mulsd %xmm4, %xmm5
addsd %xmm7, %xmm5
ucomisd %xmm5, %xmm6
jp .L9
.L8:
movups %xmm0, (%rax)
movups 64(%rsp), %xmm6
movups 80(%rsp), %xmm7
addq $104, %rsp
ret
.L9:
movq %rcx, 112(%rsp)
leaq 48(%rsp), %rcx
movsd %xmm4, 32(%rsp)
call __muldc3
movupd 48(%rsp), %xmm0
movq 112(%rsp), %rax
jmp .L8
Code: [Select]
cmul2:
.seh_endprologue
movdqu (%rdx), %xmm0
movdqu (%r8), %xmm2
movapd %xmm0, %xmm1
unpcklpd %xmm0, %xmm1
unpckhpd %xmm0, %xmm0
mulpd %xmm2, %xmm1
shufpd $1, %xmm2, %xmm2
movq %rcx, %rax
mulpd %xmm2, %xmm0
movapd %xmm1, %xmm2
subpd %xmm0, %xmm2
addpd %xmm0, %xmm1
movsd %xmm2, %xmm1
movups %xmm1, (%rcx)
ret

 :popcorn:
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 6779
  • Country: pl
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #27 on: February 25, 2022, 07:32:09 am »
glibc-2.32-r5 -> /usr/include/complex.h
This is the one to worry about.

Others are C++ which doesn't have this macro because it has constructors to deal with it.
 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #28 on: February 25, 2022, 08:49:46 am »
[... not what one could naïvely expect...]
 :popcorn:
The two code snippets are not equivalent.
Consider what happens with all the combinations of Inf, 0 and NaN: the simple routine will return some surprising results, all the pirouetting in the complex.h version is needed to keep them straight.
The way they should work is described for C11 in Annex G IEC 60559-compatible complex arithmetic.
Note that the annex is normative (if __STDC_IEC_559_COMPLEX__ is defined - which gcc does not by default, AFAICS), so a compliant implementation needs to abide by it.

So, even without declaring full compliance, they are trying to make things right.

Use -ffast-math (or -ffinite-math-only) to get the same (unsafe, but mostly OK if one accepts the non compliance) results.

Yes, definitely complex stuff... ;D
« Last Edit: February 25, 2022, 09:47:29 am by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #29 on: February 25, 2022, 12:28:35 pm »
glibc-2.32-r5 -> /usr/include/complex.h
This is the one to worry about.

Others are C++ which doesn't have this macro because it has constructors to deal with it.

Yup, that's one of the reasons why I rebuilt glibc :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: 3915
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #30 on: February 25, 2022, 12:30:40 pm »
I haven't yet understood how things work, mathcalls-helper-functions.h looks invoked several times with different data-types.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #31 on: February 25, 2022, 04:02:18 pm »
When I have to deal with numbers, I am more comfortable with Fortran.

Code: [Select]
program Complex
    implicit none

    complex z /(4,3)/  ! this is 4+3i

    print *, abs(z)    ! result is 5.00000000

end program Complex
[/font]

This result is from the GNU Fortran compiler where complex arithmetic just works.  It wasn't an afterthought, it has always been part of the language  back to at least FORTRAN IV released in 1962.
« Last Edit: February 25, 2022, 04:03:52 pm by rstofer »
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14472
  • Country: fr
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #32 on: February 25, 2022, 06:00:29 pm »
[... not what one could naïvely expect...]
 :popcorn:
The two code snippets are not equivalent.

Clearly not.

Consider what happens with all the combinations of Inf, 0 and NaN: the simple routine will return some surprising results, all the pirouetting in the complex.h version is needed to keep them straight.
The way they should work is described for C11 in Annex G IEC 60559-compatible complex arithmetic.
Note that the annex is normative (if __STDC_IEC_559_COMPLEX__ is defined - which gcc does not by default, AFAICS), so a compliant implementation needs to abide by it.

So, even without declaring full compliance, they are trying to make things right.

Use -ffast-math (or -ffinite-math-only) to get the same (unsafe, but mostly OK if one accepts the non compliance) results.

Yes, definitely complex stuff... ;D

Of course. But that's just to show that you could get unexpectedly worse performance when using the complex type in C, without necessarily realizing it, or even less so requiring the overhead in your case.

Although this is a reasonable approach, this kind of "hand-holding" is still questionable. And, if you set  -ffast-math or -ffinite-math-only, this has other implications on your code, especially if you're also using FP numbers.

Sure, expressions like 'a*c + b*d' can yield funky results or loss of precision depending on a, b, c and d using FP arithmetic. But that's true in any case, not just when dealing with complex numbers, and expressions like this are extremely common.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3915
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #33 on: February 26, 2022, 04:39:50 am »
Got tired and found a workaround

Code: [Select]
/*
 * ISO C99 Standard: 7.22 Type-generic math     <tgmath.h>
 */

#ifndef _TGMATH_H
#define _TGMATH_H       1

#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
#include <bits/libc-header-start.h>

/* Include the needed headers.  */
#include <bits/floatn.h>
#ifndef myautoproto // myhack
   #include <math.h> // myhack
#endif // myhack
#include <complex.h>
...
(/usr/include/tgmath.h)

added "-Dmyautoproto=1" *only* to the interface generator of my autobuilder

Code: [Select]
# myproject-autobuild-makefile-v5-revC
# make clean_all
- cleaning interfaces /usr/include
- cleaning interfaces app
- cleaning interfaces .
- cleaning all
# make interfaces
- touching interface private
- touching interface public
- generating interface private for app
- generating interface private for cplx
- generating interface public for app
- generating interface public for cplx
# make
- compiling app ... done
- compiling cplx ... done
- linking to app

and boooom, now it works without annoying unintelligible messages  :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: 3915
  • Country: gb
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #34 on: February 26, 2022, 05:02:59 am »
When I have to deal with numbers, I am more comfortable with Fortran.

Of course, GNU Fortran is also less messed up than Gcc, but I have to support complex numbers in the cleanest and safest way for the firmware I wrote for industrial embroidery machine and I don't want to also implement complex numbers because I am already about 7K lines of C.

The next steps are
- to get it working for Linux-{ MIPS32/be, HPPA2/32bit, PPC32/be, PPC64/be-32bit, ARM7-32bit }-glibc
- to get it working for cross-compiling, for the industrial embroidery machine, target = PPC32/be

PPC64/be-32bit will also have to support complex numbers natively for a radio-telescope application. Next month.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #35 on: February 26, 2022, 10:42:20 pm »
When I have to deal with numbers, I am more comfortable with Fortran.

Of course, GNU Fortran is also less messed up than Gcc, but I have to support complex numbers in the cleanest and safest way for the firmware I wrote for industrial embroidery machine and I don't want to also implement complex numbers because I am already about 7K lines of C.


It's pretty easy to mix C and Fortran once you get used to the idea that Fortran is 'call by reference' and C is 'call by value'.  I used an RS232 library written in C on a Fortran project by writing a little shim code.  In Fortran, a complex value is held as a 2 element vector of real numbers.  I suppose that would be a 'struct' in C were I writing my own complex library but I haven't tried it.

But really, you're probably too far along to pull the math bits out and rewrite them in Fortran.  It's just that FORTRAN was my first language and will always be my favorite.  When it comes to numbers, I tend to prefer it to all others.
« Last Edit: February 26, 2022, 10:44:46 pm by rstofer »
 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: gcc v8-v10, undefined reference to `CMPLX': what to do?
« Reply #36 on: February 27, 2022, 09:39:23 pm »
In Fortran, a complex value is held as a 2 element vector of real numbers.  I suppose that would be a 'struct' in C were I writing my own complex library but I haven't tried it.
From ISO/IEC 9899:2011 (C11 standard) "6.2.5 Types", paragraph 13:
Quote
Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
So yes, it's an array exactly as in Fortran, not a structure.
In practice, it's a difference without a distinction:
the amount of padding between members in a struct is not specified (at least, that's how I read the standard), while an array can have only as much as to guarantee alignment of its elements (due to pointer arithmetic) though I would not expect any sane compiler to actually insert pointless padding.
Nandemo wa shiranai wa yo, shitteru koto dake.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf