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

pointer to derived type component

lcoul
Beginner
825 Views
Versions used (in debug and optimized modes) :

ifort (IFORT) 10.0 20070809
gcc version 3.3.5 (Debian 1:3.3.5-13)

and

ifort (IFORT) 10.0 20070426
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)


I get a wrong result with the following test example (g95 gives the correct answer but gfortran does not want to compile Sad smiley [:(]) :

File test15.f90 :

PROGRAM test

USE iso_c_binding

TYPE, BIND(C) :: mytype
INTEGER(C_INT) :: ival
REAL(C_DOUBLE) :: dval
END TYPE

INTERFACE
FUNCTION get_c_pointer(n) RESULT BIND(C,name="get_c_pointer")
USE iso_c_binding
TYPE(C_PTR) :: r
INTEGER(C_INT),VALUE,INTENT(IN) :: n
END FUNCTION
END INTERFACE

TYPE(mytype),POINTER :: array(:)
DOUBLE PRECISION,POINTER :: vector(:)
TYPE(C_PTR) :: cptr

cptr= get_c_pointer(10)
CALL C_F_POINTER(cptr,array,(/10/))

vector => array(:)%dval

WRITE(*,*) vector

END PROGRAM

File get_c_pointer :

#include

typedef struct{
int ival;
double dval;
}mytype;

mytype* get_c_pointer(int n){
int i;
mytype *s;
s=(mytype*)malloc(n*sizeof(mytype));
for(i=0;i s.ival=i;
s.dval=i;
}
return s;
}

g95 result :

0. 1. 2. 3. 4. 5. 6. 7. 8. 9.

ifort result :

2.121995790965272E-314 9.881312916824931E-324 3.00000000000000
1.114099596794633E-313 2.964393875047479E-323 7.00000000000000
1.962949719718608E-313 2.865224816750859E-309 0.000000000000000E+000
0.000000000000000E+000



0 Kudos
12 Replies
lcoul
Beginner
825 Views
The mistake probably comes from a misalignment of double values.

Indeed, when I add a new integer variable in the definition of the derived type, then the result is OK :

FORTRAN side

TYPE, BIND(C) :: mytype
INTEGER(C_INT) :: ival,ival2
REAL(C_DOUBLE) :: dval
END TYPE

C side

typedef struct{
int ival,ival2;
double dval;
}mytype;

Result with ifort and gcc

0.000000000000000E+000 1.00000000000000 2.00000000000000
3.00000000000000 4.00000000000000 5.00000000000000
6.00000000000000 7.00000000000000 8.00000000000000
9.00000000000000

0 Kudos
Ron_Green
Moderator
825 Views
Hmm,, I'm going to have to regression test this a bit - I have the 10.1 compiler on my Mac and I get the correct answer. Have you tried the latest 10.1 compiler on your development platform?

Here's what I'm seeing on my Mac with 10.1.007 and gcc:

rwgreen$ gcc -m64 -c get_c_pointer.c

rwgreen$ ifort test15.f90 get_c_pointer.o
test15.f90(27): (col. 3) remark: LOOP WAS VECTORIZED.

mbp0017f2df31c3:~/quads/forums/30247174 rwgreen$ ./a.out
0.000000000000000E+000 1.00000000000000 2.00000000000000
3.00000000000000 4.00000000000000 5.00000000000000
6.00000000000000 7.00000000000000 8.00000000000000
9.00000000000000

0 Kudos
Steven_L_Intel1
Employee
825 Views
10.1.013 on Windows shows me the same good results Ron saw on MacOS.
0 Kudos
Ron_Green
Moderator
825 Views
I will bet $20 you are using a 32bit Linux system, yes?

I can reproduce this with the latest 10.1 iforts, but ONLY on 32bit Linux and Mac OS X. So it seems to be an issue with the 32bit compiler.

On my Mac, I can compile in 32bits:
rwgreen$ gcc -m32 -c get_c_pointer.c
rwgreen$ ifort -m32 test15.f90 get_c_pointer.o
test15.f90(27): (col. 3) remark: LOOP WAS VECTORIZED.
mbp0017f2df31c3:~/quads/forums/30247174 rwgreen$ ./a.out
2.121995790965272E-314 9.881312916824931E-324 3.00000000000000
1.114099596794633E-313 2.964393875047479E-323 7.00000000000000
1.962949719718608E-313 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000

On Linux, I used a 32bit Linux host, hence the 32bit gcc and 32bit Ifort to the same results.

If you can, use a 64bit Linux host and 64 bit gcc and ifort to work around this issue.

Please go to premier.intel.com and open a bug report. Reference T82358-CP in your Premier issue. This is the internal bug report that I opened on this. If you don't have Premier access let me know so I an assign the bug to myself instead of you.

ron
0 Kudos
lcoul
Beginner
825 Views
Yes this is a 32 bit Linux

No I cannot switch to a 64 bit system easily. I have the choice between my personal computer (core 2 duo 2.4Gz), a Cluster of 128 Linux OS nodes (32bit 3.2Gz), 1 cluster of 32 nodes (32bit 3Gz), and a farm of PCs (about 1 hundred PCs with Intel or AMD processors 32 or 64 bits). And the codes I develop must be install everywhere.

No, I haven't Premier access. I just use the free ifort version on my personal computer and an official 10.0 version on the clusters : the maintenance team managing this network has surely a Premier access but not me.

F. Jacq

0 Kudos
Steven_L_Intel1
Employee
825 Views
You have access to Intel Premier Support even with the free non-commercial license. Just register your serial number and check the box to register for support.

What I found is that the Fortran compiler needs to know whether or not the "companion C processor" inserts padding for misaligned members of structs by default. Apparently some do (MSVC) and some don't (gcc?).
0 Kudos
Ron_Green
Moderator
825 Views
OK, how about just using -malign-double with gcc?

rwgreen$ gcc -m32 -malign-double -c get_c_pointer.c
rwgreen$ ifort -m32 test15.f90 get_c_pointer.o
test15.f90(27): (col. 3) remark: LOOP WAS VECTORIZED.
mbp0017f2df31c3:~/quads/forums/30247174 rwgreen$ ./a.out
0.000000000000000E+000 1.00000000000000 2.00000000000000
3.00000000000000 4.00000000000000 5.00000000000000
6.00000000000000 7.00000000000000 8.00000000000000
9.00000000000000


Try this on your linux box.

and some cautions from our GNUish friends:
"-malign-double
-mno-align-double
Control whether GCC aligns double, long double, and long long variables on a two word boundary or a one word boundary. Aligning double variables on a two word boundary will produce code that runs somewhat faster on a `Pentium' at the expense of more memory.
On x86-64, -malign-double is enabled by default.

Warning: if you use the -malign-double switch, structures containing the above types will be aligned differently than the published application binary interface specifications for the 386 and will not be binary compatible with structures in code compiled without that switch. "

SO you will have to use that switch for ALL your source files. But hey, as a side benefit you will get a little performance increase (in theory).

cheers

ron
0 Kudos
Ron_Green
Moderator
825 Views
Just so it's crystal clear, don't use -m32 on your Linux system. This is a Mac-ism.
0 Kudos
srinath
Beginner
825 Views
this is an important issue for me..but I can't even use the iso_c_binding module. How do I link in the appropriate module?

0 Kudos
TimP
Honored Contributor III
825 Views
gcc and gfortran switch from 64-bit to 32-bit code by the -m32 switch. The equivalent switch with ifort is to set environment variables according to the scripts in /opt/intel/fce/bin (64-bit) or /opt/intel/fc/bin (32-bit, if both are installed).
iso_c_binding is invoked by the USE, in accordance with any textbook, or see e.g.
http://www.fortran.bcs.org/2002/interop.htm

0 Kudos
srinath
Beginner
825 Views
I should clarify. I used the discussion's first example as an introduction to using c-bind. I copied the above example, and on a mac w/ Leopard, using the 32-bit ifort, I saved the 2 portions of code in a fortran and c file. ifort -c test1.f failed at compile time, even though I source the variables in the intel variable script. The error is that the "use" statement :
fortcom: Error: c_bindtest.f, line 4: Error in opening the compiled module file. Check INCLUDE paths. [ISO_C_BINDINGROGRAMTEST]
USE iso_c_binding

I don't think I have to explicitly include the intel compiler include path, do I?
0 Kudos
srinath
Beginner
825 Views
Fixed. I was using a *.f suffix, the correct one is *.f90.
Sorry for the confusion.

0 Kudos
Reply