Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29486 Discussions

passing float _Complex from C to Fortran

Alfredo_Buttari
Beginner
2,314 Views

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:[cpp]#include void func(float _Complex x); int main(){ func((float _Complex)_Complex_I); return 1; } [/cpp] Fortran code:[fortran]subroutine func(x) bind(c) use iso_c_binding complex(c_float_complex), value :: x write(*,*)'x:',x return end subroutine func[/fortran] 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

0 Kudos
1 Solution
mecej4
Honored Contributor III
2,314 Views
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.

View solution in original post

0 Kudos
11 Replies
mecej4
Honored Contributor III
2,314 Views
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?
0 Kudos
Alfredo_Buttari
Beginner
2,314 Views
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
0 Kudos
mecej4
Honored Contributor III
2,315 Views
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.
0 Kudos
Alfredo_Buttari
Beginner
2,314 Views
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
0 Kudos
Steven_L_Intel1
Employee
2,314 Views
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.
0 Kudos
mecej4
Honored Contributor III
2,314 Views
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.
0 Kudos
Alfredo_Buttari
Beginner
2,314 Views
Steve, Mecej,
I couldn't ask for a better explanation. Thanks for making this clear.
best regards
Alfredo
0 Kudos
Alfredo
Beginner
2,314 Views
Mecej,
just to inform that this issue is still present in the new12.0.0.084 version o the ifort compiler.
regards
alfredo
0 Kudos
mecej4
Honored Contributor III
2,314 Views
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.
0 Kudos
Kevin_D_Intel
Employee
2,314 Views

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)
0 Kudos
Kevin_D_Intel
Employee
2,314 Views
Please pardon the delayed update. This defect is fixed in the Intel® Fortran Compiler XE Update 6 (12.1.0.233 - Linux)
0 Kudos
Reply