passing float _Complex from C to Fortran

passing float _Complex from C to Fortran

Alfredo Buttari's picture

Hello,I'm trying to pass some complex data from a C to a Fortran program without success for the moment.I managed to reproduce the problem in the small example belowC code:

#include void func(float _Complex x); int main(){ func((float _Complex)_Complex_I); return 1; } 
Fortran code:
subroutine func(x) bind(c) use iso_c_binding complex(c_float_complex), value :: x write(*,*)'x:',x return end subroutine func
The value of x printed is(0.0000000E+00,1.5932920E-10). Am I doing anything wrong here?Note that the same code works fine with GNU and IBM compilers. Moreover, if "float" is replaced with "double" in both sources, then it works ok.Can anybody help please?thanks in advance

12 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
mecej4's picture

No problems with gcc 4.5 and IFort 11.1.073 (32 bit) on X64 Linux:

$ cc -m32 -g -c cplx.c
$ ifort -g -nofor-main cplx.o cfun.f90
$ ./a.out
x: (0.0000000E+00,1.000000)
$

If you are running on an Apple-Mac, have you checked regarding the X-Code bugs and work-arounds?

Alfredo Buttari's picture

Hello, I'm running on a linux 64-bit system with intel icc and ifort V11.1.072. This is how I compile: $ icc -g -c comp_main.c $ ifort -g -nofor_main comp_fun.f90 comp_main.o $ ./a.out x: (0.0000000E+00,1.5932920E-10) maybe I should check if it works with 11.1.073? Thanks Mecej

mecej4's picture
Best Reply

I see the error with the 64-bit version of 11.1.073 on Linux-x64. The IFort compiled subroutine expects to see the real and imaginary parts in separate xmm registers, whereas C (Gcc or Intel C) passes the parts in the upper and lower halves of xmm0. Thus, the IFort compiled function takes the trash in xmm1 and prints it as the imaginary part.

It would be interesting to see if the soon-to-be-released 64-bit version of the Intel compiler also has this problem.

Alfredo Buttari's picture

Dear Mecej, easy to imagine that if the argument is passed by reference instead of by value then everything works. Now the question is, is there a correct behavior for passing complex type arguments by value? Is it left to the compiler to decide whether to put the complex number in one or two registers? In this case this means that C codes compiled with different compilers may not be compatible, right? this looks pretty bad. Thanks for your help Alfredo

Steve Lionel (Intel)'s picture

There is an "ABI" (Application Binary Interface) document that describes, for a given architecture, how such things are done, but who defines this can be a subject of discussion. On Linux, the gcc documents are usually considered the standard here and I know that the Intel compiler has made changes over time to match that.

This issue sounds vaguely familiar and I'll look to see if we know about this.

Steve
mecej4's picture

Alfredo,

Although this statement is correct in this specific example, I would not count on the assumption in general:

"if the argument is passed by reference instead of by value then everything works"

because in C complex variables are structures, whereas in Fortran COMPLEX is an INTRINSIC type. Since structures are subject to padding/packing, mismatches can occur even if passing is done by reference.

Secondly, I think that the question

"In this case this means that C codes compiled with different compilers may not be compatible, right?"

puts the blame on the wrong entity. On Linux, for good or bad, GCC sets the standard and, as far as I know, did not deviate from the ABI defined by AMD. Discrepancies such as in this problem, therefore, are attributable to Fortran compilers rather than C compilers. In fact, your code runs fine with GFortran.

I am sure that Intel will do the right thing, once the issue is tagged as a bug.

By the way, the code runs correctly on IA64 (IFort 11.1.072, GCC) and Windows-XP64 (IFort 11.1.067-X64, Microsoft C). On the latter platform, however, Microsoft C uses an ABI that is almost completely different from the AMD/INTEL ABI, so GCC and its conventions do not enter the picture.

Alfredo Buttari's picture

Steve, Mecej, I couldn't ask for a better explanation. Thanks for making this clear. best regards Alfredo

Alfredo's picture

Mecej, just to inform that this issue is still present in the new12.0.0.084 version o the ifort compiler. regards alfredo

mecej4's picture

Alfredo, the problem seems to be worse (more pervasive, and not specific to C-interoperability) than I thought. I have modified your code and posted a reproducer here which is entirely in Fortran.

Kevin Davis (Intel)'s picture

I reported this defect to Development (internal tracking id noted below) and will keep both posts updated with new status as I learn it.

Thank you again mecej4 for isolation details and convenient reproducer.

(Internal tracking id: DPD200198349)

(Resolution Update on 10/14/2012): This defect is fixed in the Intel® Fortran Compiler XE Update 6 (12.1.0.233 - Linux)

Kevin Davis (Intel)'s picture

Please pardon the delayed update. This defect is fixed in the Intel® Fortran Compiler XE Update 6 (12.1.0.233 - Linux)

Login to leave a comment.