Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Fortran Programming Language

Reading complex multidimensionalarrays from C


Hi,

I defined a multidimensional Array (with complex values) in Fortran:

PROGRAM Hello
 complex, dimension(2,2) :: A

 A(1,1) = cmplx(3, 2)
 A(1,2) = cmplx(3, 7)
 A(2,1) = cmplx(9, 9)
 A(2,2) = cmplx(2, 7)

 CALL test(A,2,2)
END

I tried to read values with the folowing C function:

#include <stdio.h>

typedef struct {
    double dr;
    double di;

} fcomplex;

int test_ (fcomplex *fc, int *n, int *m) {
    printf("YAY: %f + %fi\n", fc->dr, fc->di);
    return(0);

}

I compiled it like this:

gfortran -c -g testF2.f
gcc -c -g testC.c
gfortran -g -o test testC.o testF2.o

It compiles well, but when I execute ./test I get:
YAY: 2.000000 + 262144.063538i

So could anyone please give me some hints how to do it right?

Regards,
Timo

On Apr 28, 12:55 pm, t@hrz.tu-chemnitz.de wrote:

> Hi,

> I defined a multidimensional Array (with complex values) in Fortran:

> PROGRAM Hello
>  complex, dimension(2,2) :: A

>  A(1,1) = cmplx(3, 2)
>  A(1,2) = cmplx(3, 7)
>  A(2,1) = cmplx(9, 9)
>  A(2,2) = cmplx(2, 7)

>  CALL test(A,2,2)

You have an argument mismatch here. You are passing a pointer to the
start of A, then two integers. Your routine expects a pointer to an
array of two doubles. The type mismatch is corrected below.

The proper syntax is:

CALL test(A(2,2))

> END

> I tried to read values with the folowing C function:

> #include <stdio.h>

> typedef struct {
>     double dr;
>     double di;

The components of a Fortran COMPLEX are two variables of type default
REAL. In Fortran this is single precision - which is FLOAT in C. You
are not guaranteed that a particular compiler supports what might be
declared as (non-standard) DOUBLE COMPLEX or COMPLEX*16 or a type of
complex using kinds).

float dr;
float di;

> } fcomplex;

> int test_ (fcomplex *fc, int *n, int *m) {
>     printf("YAY: %f + %fi\n", fc->dr, fc->di);
>     return(0);

> }

> I compiled it like this:

> gfortran -c -g testF2.f

You have posted free form source but gfortran expects fixed format
with a file extension of .f:

gfortran -c -g -ffree-form testF2.f

> gcc -c -g testC.c

On my system I need to add a path to the include files. You may not
need this:

gcc -c -g -I\gfortran\include testC.c

> gfortran -g -o test testC.o testF2.o

OK

> It compiles well, but when I execute ./test I get:
> YAY: 2.000000 + 262144.063538i

YAY: 2.000000 + 7.000000i

> So could anyone please give me some hints how to do it right?

See comments interspersed with your code and output.

> Regards,
> Timo

You have fallen into several traps common in mixed language
programming. You have two different sources of argument mismatch here.
First, your incorrect syntax gives you a mismatch in the NUMBER of
arguments. Second, the TYPES of your arguments do not correspond. In
Fortran you are using single precision, but in C you are using double.

Worse, your compilers will not catch this type of error. If you had
included an explicit interface (somewhat analagous to a function
prototype in C) for your C routine in Fortram, you might have caught
the syntax error, but not the type misatch error.

-- e-mail: epc8 at juno dot com
-- elliot

On Apr 28, 1:58 pm, e p chandler <e@juno.com> wrote:

Excuse replying to self, but I messed up your declaration on the C
side too! :-(. If you really want to pass an array and two subscripts
then you have to account for two factors in your C code.

1. Fortran subscripts (unless declared otherwise) start at 1. In C
arrays are 0 based.
2. Fortran is column major but C is row major. So with 2 subscripts
you need to interchange them on the C side.
I won't try to suggest what you might write in C to handle the 3
argument case.

int test_ (fcomplex *fc) {

And I made the same mistake as you did in my original reply.

Hi!

> 1. Fortran subscripts (unless declared otherwise) start at 1. In C
> arrays are 0 based.
> 2. Fortran is column major but C is row major. So with 2 subscripts
> you need to interchange them on the C side.

Yes, I already know this, but it didn't help :-)

> I won't try to suggest what you might write in C to handle the 3
> argument case.

:-( That was exactly what I need to do.

Regards,
Timo

e p chandler <e@juno.com> wrote:

> You
> are not guaranteed that a particular compiler supports what might be
> declared as (non-standard) DOUBLE COMPLEX or COMPLEX*16 or a type of
> complex using kinds).

Yes, support of double precision complex is guaranteed by the standard
as of f90. (The code already uses an f90 syntax and the mentioned
compilers are f90/f95 ones). You do have to use the f90 kind syntax to
declare them; the syntax forms "double cimplex" and complex*16 were not
standardized, but the functionality of double precision complex was.

In fact, the f90 standard requires that *EVERY* real kind have a
corresponding complex kind. I have seen vendors try to rationalize that
they can support a quad precision real without also supporting a quad
precision complex, but I don't think that the rationalizations hold up.
The usual rationalization claims that the quad precision real is an
extension and thus that the requirement for a corresonding complex
doesn't apply.

However, I don't buy that rationalization because I don't think such
vendors actually implement quad precision real in a way that counts as
an extension. An extension can't make standard conforming code invalid;
if that happens, the compiler is violating the standard rather than
extending it. The distinction is critical.

For example, selected_real_kind is required to return either a valid
kind number or a negative error indication. Any positive number returned
from it is supposed to be valid. I claim it is a compiler violation of
the standard - not an extension - if a positive value returned from
selected_real_kind can't be used as a complex kind value.

It might be possible to do a quad precision real in a way that counted
as an extension and had no corresponding quad complex, but I bet that's
not what any vendors do.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

Richard Maine wrote:

(snip)

> In fact, the f90 standard requires that *EVERY* real kind have a
> corresponding complex kind. I have seen vendors try to rationalize that
> they can support a quad precision real without also supporting a quad
> precision complex, but I don't think that the rationalizations hold up.
> The usual rationalization claims that the quad precision real is an
> extension and thus that the requirement for a corresonding complex
> doesn't apply.
> However, I don't buy that rationalization because I don't think such
> vendors actually implement quad precision real in a way that counts as
> an extension. An extension can't make standard conforming code invalid;
> if that happens, the compiler is violating the standard rather than
> extending it. The distinction is critical.

If one implemented REAL*16, but not SELECTED_REAL_KIND(30)
would that qualify as an extension not requiring a corresponding
COMPLEX*32?   Note that IBM has supported both REAL*16 and
COMPLEX*32 since somewhere around 1968.

-- glen

glen herrmannsfeldt <g@ugcs.caltech.edu> wrote:
> Richard Maine wrote:
> > In fact, the f90 standard requires that *EVERY* real kind have a
> > corresponding complex kind. I have seen vendors try to rationalize that
> > they can support a quad precision real without also supporting a quad
> > precision complex, but I don't think that the rationalizations hold up...
> If one implemented REAL*16, but not SELECTED_REAL_KIND(30)
> would that qualify as an extension not requiring a corresponding
> COMPLEX*32?

Potentially. But I can't make a judgement about the standard conformance
of a compiler based on a hypothetical situation described in a single
sentence. I also doubt (though I'm not sure) that there is a single f90
compiler that does this, which makes the question a bit academic.

Types are pretty fundamental things and show up all over the place in
the language. I can't even come up with a list of all the potentially
relevant things. The selected_real_kind issue was just the first thing
that came to mind, not the final arbiter of whether an implementation
was standard conforming.

The real*16 syntax is nonstandard and thus a compiler can do anything
with it (as long as it has the capability to diagnose the use of the
nonstandard syntax). But supporting a particular real precision involves
a whole lot more than that one bit of syntax. Saying that a hypothetical
compiler does the syntax that way doesn't tell me anything about all the
other issues, which might come up in code not using the nonstandard
syntax.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

Re: passing an array of DOUBLE COMPLEX (sic) from Fortran to C

On Apr 28, 2:32 pm, t@m34s24.vlinux.de wrote:

Ouch. Well if you insist on doing the address calculation in C, then
you need to know the number of rows in the array and you need to pass
that number as an argument to your subroutine.

Here is some Fortran code and some C code that apparently works. I've
changed the extension of the Fortran file to .f95 so that the free-
form command line option is not needed. Note that my C code modifies
one of the arguments passed to the routine. Also there may be a better
way to write this in C. (Doing arithmetic on a pointer in C takes the
size of the object that the pointer references into account.) Lastly,
I've changed things on the Fortran side so that the C side receives
doubles instead of floats. I will leave the discussion of kinds in
Fortran and why I added a third parameter to cmplx() for others.

testF2.f95:

PROGRAM Hello
 integer,parameter :: dp = selected_real_kind(15)
 complex(kind=dp), dimension(3,5) :: A

 A(1,1) = cmplx(3, 2, kind=dp)
 A(1,2) = cmplx(3, 7, kind=dp)
 A(2,1) = cmplx(9, 9, kind=dp)
 A(2,2) = cmplx(2, 7, kind=dp)

 CALL test(A,1,1,3) ! last argument is number of rows
 CALL test(A,1,2,3)
 CALL test(A,2,1,3)
 CALL test(A,2,2,3)

END

testC.c:

#include <stdio.h>

typedef struct {
    double dr;
    double di;

} fcomplex;

int test_ (fcomplex *fc, int *n, int *m, int *r) {
/*
   modify pointer to calculate address
   argument r = number of rows in array
*/
    fc = fc + ((*m)-1) * (*r) + ((*n)-1);
    printf("YAY: %f + %fi\n", fc->dr, fc->di);
    return(0);

}

make.bat:

gfortran -c -g testF2.f95
gcc -c -g -I\gfortran\include testC.c
gfortran -g -o test testC.o testF2.o

program output:

YAY: 3.000000 + 2.000000i
YAY: 3.000000 + 7.000000i
YAY: 9.000000 + 9.000000i
YAY: 2.000000 + 7.000000i

Note: on my system '\n' is not expanded to CR/LF when output is
redirected to a file.

-- e-mail: epc8 at juno dot com
-- elliot

"e p chandler" <e@juno.com> wrote in message
news:1177783128.657920.82030@u30g2000hsc.googlegroups.com...

I'm still back here, having now just received an opinion from C.  Gotta run,
though.  Does the fortran part need to be built as a .dll?
http://www.billfordx.net/2007-04-28b.htm
--
WW
On Apr 28, 11:38 pm, "Wade Ward" <inva@invalid.net> wrote:

Yes. The OP needs a Fortran DLL. I've done similar stuff interfacing
Visual Basic / VBA and Fortran for various GUI builders and Fortrans.
If you want to try this yourself, get and install the MinGW version of
gfortran. This includes C.

see: http://quatramaran.ens.fr/~coudert/gfortran/gfortran-windows.exe

Run the program and install in a convenient directory, say \gfortran.
Look back in this thread to see the commands I used to compile the
source files and create the .exe file.

-- Elliot

On Apr 28, 11:47 pm, e p chandler <e@juno.com> wrote:

OOPS. I've intermixed two different threads. This problem is mixed
language, but it is Fortran + C, not a DLL at all. GUI + Fortran is a
different thread.

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc