Home > Archive > Fortran > April 2007 > Reading complex multidimensionalarrays from C
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Reading complex multidimensionalarrays from C
|
|
| timos@hrz.tu-chemnitz.de 2007-04-28, 7:04 pm |
| 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
| |
| e p chandler 2007-04-28, 7:04 pm |
| 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
| |
| e p chandler 2007-04-28, 7:04 pm |
| On Apr 28, 1:58 pm, e p chandler <e...@juno.com> wrote:
> On Apr 28, 12:55 pm, t...@hrz.tu-chemnitz.de wrote:
>
>
>
>
>
>
> 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))
>
>
>
>
>
> 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;
>
>
>
>
>
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) {
[color=darkred]
>
>
>
> You have posted free form source but gfortran expects fixed format
> with a file extension of .f:
>
> gfortran -c -g -ffree-form testF2.f
>
>
> 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
>
>
> OK
>
>
>
>
> YAY: 2.000000 + 7.000000i
>
>
>
>
> See comments interspersed with your code and output.
>
>
> 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.
>
And I made the same mistake as you did in my original reply.
> -- e-mail: epc8 at juno dot com
> -- elliot
| |
| timos@m34s24.vlinux.de 2007-04-28, 7:04 pm |
| 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
| |
| Richard Maine 2007-04-28, 7:04 pm |
| e p chandler <epc8@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
| |
| glen herrmannsfeldt 2007-04-28, 7:04 pm |
| 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
| |
| Richard Maine 2007-04-28, 7:04 pm |
| glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
> Richard Maine wrote:
[color=darkred]
> 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
| |
| e p chandler 2007-04-28, 7:04 pm |
| Re: passing an array of DOUBLE COMPLEX (sic) from Fortran to C
On Apr 28, 2:32 pm, t...@m34s24.vlinux.de wrote:
> Hi!
>
>
> Yes, I already know this, but it didn't help :-)
>
>
> :-( That was exactly what I need to do.
>
> Regards,
> Timo
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
| |
| Wade Ward 2007-04-29, 4:15 am |
|
"e p chandler" <epc8@juno.com> wrote in message
news:1177783128.657920.82030@u30g2000hsc.googlegroups.com...
> On Apr 28, 12:55 pm, t...@hrz.tu-chemnitz.de wrote:
>
> 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))
>
>
> 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;
>
>
> You have posted free form source but gfortran expects fixed format
> with a file extension of .f:
>
> gfortran -c -g -ffree-form testF2.f
>
>
> 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
>
>
> OK
>
>
> YAY: 2.000000 + 7.000000i
>
>
> See comments interspersed with your code and output.
>
>
> 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.
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
| |
| e p chandler 2007-04-29, 4:15 am |
| On Apr 28, 11:38 pm, "Wade Ward" <inva...@invalid.net> wrote:
> "e p chandler" <e...@juno.com> wrote in messagenews: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
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/...ran-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
| |
| e p chandler 2007-04-29, 4:15 am |
| On Apr 28, 11:47 pm, e p chandler <e...@juno.com> wrote:
> 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.
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.
>
> see:http://quatramaran.ens.fr/~coudert/...ran-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.
| |
| Wade Ward 2007-04-29, 10:04 pm |
|
"e p chandler" <epc8@juno.com> wrote in message
news:1177818469.199678.100230@y5g2000hsa.googlegroups.com...[color=darkred]
> On Apr 28, 11:38 pm, "Wade Ward" <inva...@invalid.net> wrote:
[color=darkred]
[color=darkred]
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 program Hello
I added explicit ends to what I think is now a reasonable version of a
fortran caller.
[color=darkred]
On the C side this is how you compile. What about this command line tells C
to not worry about finding main?
[color=darkred]
Unless you keep your C stuff with your fortran stuff, you'll need to adjust
directories. Working out of IDE's, I usually put the files that the fortran
linker is looking for in the same directory.
[color=darkred]
I think I'm having thread trouble too, or maybe I've got too many irons in
the fire. I thought you'd left it last night to where you pass the
dimension of some array. This screenshot seemed informative:
http://www.billfordx.net/2007-04-29.htm
--
WW
| |
| e p chandler 2007-04-29, 10:04 pm |
| On Apr 29, 9:52 pm, "Wade Ward" <inva...@invalid.net> wrote:
> "e p chandler" <e...@juno.com> wrote in messagenews:1177818469.199678.100230@y5g2000hsa.googlegroups.com...
>
>
>
[snip snip snip]
>
> On the C side this is how you compile. What about this command line tells C
> to not worry about finding main?
-c means just compile to object code - the routine need not be main
>
>
>
> Unless you keep your C stuff with your fortran stuff, you'll need to adjust
> directories. Working out of IDE's, I usually put the files that the fortran
> linker is looking for in the same directory.
Here I am adding a directory for the _C_compiler_ to find the include
files like "stdio.h". Perhaps if I installed this somewhere else it
might find the include files by itself. Normally I don't worry about
this because I am only compiling Fortran programs. In this case it's
convenient to use this distribution of gfortran because it includes a
C compiler, include (header) files, etc.
> I think I'm having thread trouble too, or maybe I've got too many irons in
> the fire. I thought you'd left it last night to where you pass the
> dimension of some array. This screenshot seemed informative:http://www.billfordx.net/2007-04-29.htm
> --
> WW-
Yes, I've several different projects in recent postings.
(Sorry about that!)
-- elliot
| |
| Wade Ward 2007-04-30, 4:09 am |
|
"Richard Maine" <nospam@see.signature> wrote in message
news:1hxa5eb.hwhr9n15mjp7sN%nospam@see.signature...
> glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
>
>
>
See below.
[color=darkred]
> 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.
I specifically recall what the C standard has to say about Glen's question,
if it were posed of the C language. My guess is that the wording is very
much the same in fortran. I think the spirit of it says "yes" to his
question.
--
WW
| |
| glen herrmannsfeldt 2007-04-30, 4:09 am |
| Richard Maine wrote:
(I wrote)
[color=darkred]
> 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.
It seems that there isn't much demand for it. More demand would get
more compiler writers interested.
> 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.
I am now trying to remember almost to my first Fortran program.
One of the favorite beginner programs is a square root table, and
I wanted to make a REAL*16 table. In the end, it turned out that
the compiler I was using didn't support REAL*16. While trying
to figure that out, it was suggested that I needed to declare
QSQRT as REAL*16, and also that I would need QFLOAT instead of
FLOAT to get the argument type right. So, yes, I hadn't thought
all the way through what happens if you have a non-standard type.
Among others, it might require one to declare things that one
ordinarily wouldn't need to declare.
-- glen
|
|
|
|
|