|
|
 |
 |
 |
 |
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:
> 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); > > }
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) {
> > 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.
And I made the same mistake as you did in my original reply.
> -- e-mail: epc8 at juno dot com > -- elliot
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:
> 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
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...
> 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.
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:
> "e p chandler" <e @juno.com> wrote in message news:1177783128.657920.82030@u30g2000hsc.googlegroups.com... > > 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. > 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/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:
> 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... > > > 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. > > 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.
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.
|
 |
 |
 |
 |
|