|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Vexing problems arising from mixing F9x and F77 code
A recent thread produced an illuminating discussion of the difficulties/inadvisability of mixing C and Fortran I/O (Message-ID: <1178982836.458326.3@w5g2000hsg.googlegroups.com>) Similar problems can occur when calling older F77 routines from F9x callers. Such calls may be made when using the high quality F77 routines from, say, Netlib, with F9x features used/desired/necessary in the caller. Such F90->F77 calls may also be needed when the called routines reside in an F77 library such as ACML, MKL, NAGF or IMSL, and the source code is not available. Here is a simple example to illustrate (all tests run in Linux). The F9x caller: !_______________________________________________________ program iotest integer :: i,j,nlin=0 character(len=8) :: nam do j=1,5 read(*,'(I2,1x,A)')i,nam end do nlin=5 call f77sub(nlin) do while(.true.) read(*,'(I2,1x,A)',end=100)i,nam write(*,'(1x,I2,1x,A)')i,nam nlin=nlin+1 end do 100 write(*,'(1x,I2," lines read")')nlin end program iotest !________________________________________________________ The F77 subroutine: c------------------------------------------------ subroutine f77sub(nlin) integer i,j,nlin character*8 nam do 5 j=6,10 read(*,'(I2,1x,A)',iostat=ios)i,nam if(ios.ne.0)then write(*,*)' Read error in F77sub, iostat=',ios stop end if write(*,'(" f77sub: ",I2,1x,A)')i,nam 5 continue nlin=nlin+5 write(*,'(" Prior to return from f77sub, nlin = ",I2)')nlin return end c------------------------------------------------- The data file "dat": 1 Aaa1 2 Aaa2 3 Aaa3 4 Aaa4 5 Aaa5 6 Bbb1 7 Bbb2 8 Bbb3 9 Bbb4 10 Bbb5 11 Ccc1 12 Ccc2 Compiling the main and the subroutine using the same compiler works: TST> g95 iotest.f90 f77sub.f TST> ./a.out < dat f77sub: 6 Bbb1 f77sub: 7 Bbb2 f77sub: 8 Bbb3 f77sub: 9 Bbb4 f77sub: 10 Bbb5 Prior to return from f77sub, nlin = 10 11 Ccc1 12 Ccc2 12 lines read Now let us see the pitfall; suppose that f77sub is only available as g77-compiled object code. TST> g77 TST> g95 iotest.f90 f77sub.o -g95 complains: "f77sub.f:(.text+0x36): undefined reference to `s_rsfe'" .... many more such missing ... but we know how to fix this: TST> g95 iotest.f90 f77sub.o -lg2c However, when we run the resulting program, it fails: TST> ./a.out < dat Read error in F77sub, iostat= -1 If you are not amused yet, try using f95 (NAG) instead of g95, but still use the g77 compiled subroutine: TST> f95 iotest.f90 f77sub.o -lg2c This time, the program works correctly! In this sense, then, NAG f95 shows closer affinity to g77 than does g95. -- mecej4
On 16 mei, 15:26, mecej4 <mec@operamail.com> wrote:
> A recent thread produced an illuminating discussion of the > difficulties/inadvisability of mixing C and Fortran I/O (Message-ID: > <1178982836.458326.3 @w5g2000hsg.googlegroups.com>) > Similar problems can occur when calling older F77 routines from F9x callers. > Such calls may be made when using the high quality F77 routines from, say, > Netlib, with F9x features used/desired/necessary in the caller. > Such F90->F77 calls may also be needed when the called routines reside in an > F77 library such as ACML, MKL, NAGF or IMSL, and the source code is not > available. > Here is a simple example to illustrate (all tests run in Linux). > The F9x caller: > !_______________________________________________________ > program iotest > integer :: i,j,nlin=0 > character(len=8) :: nam > do j=1,5 > read(*,'(I2,1x,A)')i,nam > end do > nlin=5 > call f77sub(nlin) > do while(.true.) > read(*,'(I2,1x,A)',end=100)i,nam > write(*,'(1x,I2,1x,A)')i,nam > nlin=nlin+1 > end do > 100 write(*,'(1x,I2," lines read")')nlin > end program iotest > !________________________________________________________ > The F77 subroutine: > c------------------------------------------------ > subroutine f77sub(nlin) > integer i,j,nlin > character*8 nam > do 5 j=6,10 > read(*,'(I2,1x,A)',iostat=ios)i,nam > if(ios.ne.0)then > write(*,*)' Read error in F77sub, iostat=',ios > stop > end if > write(*,'(" f77sub: ",I2,1x,A)')i,nam > 5 continue > nlin=nlin+5 > write(*,'(" Prior to return from f77sub, nlin = ",I2)')nlin > return > end > c------------------------------------------------- > The data file "dat": > 1 Aaa1 > 2 Aaa2 > 3 Aaa3 > 4 Aaa4 > 5 Aaa5 > 6 Bbb1 > 7 Bbb2 > 8 Bbb3 > 9 Bbb4 > 10 Bbb5 > 11 Ccc1 > 12 Ccc2 > Compiling the main and the subroutine using the same compiler works: > TST> g95 iotest.f90 f77sub.f > TST> ./a.out < dat > f77sub: 6 Bbb1 > f77sub: 7 Bbb2 > f77sub: 8 Bbb3 > f77sub: 9 Bbb4 > f77sub: 10 Bbb5 > Prior to return from f77sub, nlin = 10 > 11 Ccc1 > 12 Ccc2 > 12 lines read > Now let us see the pitfall; suppose that f77sub is only available as > g77-compiled object code. > TST> g77 > TST> g95 iotest.f90 f77sub.o > -g95 complains: > "f77sub.f:(.text+0x36): undefined reference to `s_rsfe'" > .... many more such missing ... > but we know how to fix this: > TST> g95 iotest.f90 f77sub.o -lg2c > However, when we run the resulting program, it fails: > TST> ./a.out < dat > Read error in F77sub, iostat= -1 > If you are not amused yet, try using f95 (NAG) instead of g95, but still use > the g77 compiled subroutine: > TST> f95 iotest.f90 f77sub.o -lg2c > This time, the program works correctly! In this sense, then, NAG f95 shows > closer affinity to g77 than does g95. > -- mecej4
This has little to do with Fortran 90 versus FORTRAN 77, but rather with the compatibility of compilers! I know that the gfortran compiler and apparently its brother/cousin g95 dropped binary compatibility with g77 because it was impossible to maintain that compatibility. Perhaps NAG put more effort into this as g77 was pretty much a standard under Linux, as was/is gcc for C. I am not happy about this situation either (I have seen it with Intel Fortran and CVF too), but there is little a non-compiler builder can do about it. Regards, Arjen
On 2007-05-16 10:26:48 -0300, mecej4 <mec@operamail.com> said:
> A recent thread produced an illuminating discussion of the > difficulties/inadvisability of mixing C and Fortran I/O (Message-ID: > <1178982836.458326.3 @w5g2000hsg.googlegroups.com>) > Similar problems can occur when calling older F77 routines from F9x callers. > Such calls may be made when using the high quality F77 routines from, say, > Netlib, with F9x features used/desired/necessary in the caller. > Such F90->F77 calls may also be needed when the called routines reside in an > F77 library such as ACML, MKL, NAGF or IMSL, and the source code is not > available. > Here is a simple example to illustrate (all tests run in Linux). > The F9x caller: > !_______________________________________________________ > program iotest > integer :: i,j,nlin=0 > character(len=8) :: nam > do j=1,5 > read(*,'(I2,1x,A)')i,nam > end do > nlin=5 > call f77sub(nlin) > do while(.true.) > read(*,'(I2,1x,A)',end=100)i,nam > write(*,'(1x,I2,1x,A)')i,nam > nlin=nlin+1 > end do > 100 write(*,'(1x,I2," lines read")')nlin > end program iotest > !________________________________________________________ > The F77 subroutine: > c------------------------------------------------ > subroutine f77sub(nlin) > integer i,j,nlin > character*8 nam > do 5 j=6,10 > read(*,'(I2,1x,A)',iostat=ios)i,nam > if(ios.ne.0)then > write(*,*)' Read error in F77sub, iostat=',ios > stop > end if > write(*,'(" f77sub: ",I2,1x,A)')i,nam > 5 continue > nlin=nlin+5 > write(*,'(" Prior to return from f77sub, nlin = ",I2)')nlin > return > end > c------------------------------------------------- > The data file "dat": > 1 Aaa1 > 2 Aaa2 > 3 Aaa3 > 4 Aaa4 > 5 Aaa5 > 6 Bbb1 > 7 Bbb2 > 8 Bbb3 > 9 Bbb4 > 10 Bbb5 > 11 Ccc1 > 12 Ccc2 > Compiling the main and the subroutine using the same compiler works: > TST> g95 iotest.f90 f77sub.f > TST> ./a.out < dat > f77sub: 6 Bbb1 > f77sub: 7 Bbb2 > f77sub: 8 Bbb3 > f77sub: 9 Bbb4 > f77sub: 10 Bbb5 > Prior to return from f77sub, nlin = 10 > 11 Ccc1 > 12 Ccc2 > 12 lines read > Now let us see the pitfall; suppose that f77sub is only available as > g77-compiled object code. > TST> g77 > TST> g95 iotest.f90 f77sub.o > -g95 complains: > "f77sub.f:(.text+0x36): undefined reference to `s_rsfe'" > .... many more such missing ... > but we know how to fix this: > TST> g95 iotest.f90 f77sub.o -lg2c > However, when we run the resulting program, it fails: > TST> ./a.out < dat > Read error in F77sub, iostat= -1 > If you are not amused yet, try using f95 (NAG) instead of g95, but still use > the g77 compiled subroutine: > TST> f95 iotest.f90 f77sub.o -lg2c > This time, the program works correctly! In this sense, then, NAG f95 shows > closer affinity to g77 than does g95. > -- mecej4
I think you are more than a little confused on the distinction between mixing languages and mixing compilers for the same language. Try mixing object from Intel and G77. All bets are off. Etc, etc,... A frequent question is why the IMSL/NAG/etc libraries for compiler X does not work for compiler Y. The answer is "Why would you expect it to?" See below. At one time in the past you could not even mix the object code from the IBM Fortran IV G and IBM Fortran IV H even though they shared a programmers manual. They had been writen by rather separate development groups with different objective. G was good at debugging and H was all about optimization. The various compilers for the same language will usually not share their run time libraries. The little luck you have observed is a result of you test cases being Fortrans that have "borrowed" their run time libraries from a related C compiler. Some even claim that they are not true compilers as they share the GCC back ends, but that is an uninformed overstatement. (NAG can use other backends on some platforms as well.) Compile the "F77" using a F95 compiler and the fact that F77 is a subset of F95 that typically is in fixed format source format. Compile the "F95" using the SAME F95 compiler set to use the typical free format source form and you will have no problems. This is a matter of compiler options and/or file name extensions. There is no F77 as it is all just legacy F95 that often uses fixed form amd still works with really old compilers.
Gordon Sande wrote:
(snip) > I think you are more than a little confused on the distinction between > mixing languages and mixing compilers for the same language.
It isn't so obvious either way. Some of the problems with mixing languages have to do with different calling methods. C uses pass by value and Fortran doesn't. VAX/VMS attempted a standardized calling method over all languages, with ways to override the language defaults when needed. There are a few incompatible calling methods for IA32 machines, and often ways to use different methods when needed. > Try mixing object from Intel and G77. All bets are off. Etc, etc,... > A frequent question is why the IMSL/NAG/etc libraries for compiler > X does not work for compiler Y. The answer is "Why would you expect > it to?" See below. > At one time in the past you could not even mix the object code > from the IBM Fortran IV G and IBM Fortran IV H even though they > shared a programmers manual. They had been writen by rather > separate development groups with different objective. G was good > at debugging and H was all about optimization.
I never knew about any incompatibilities. They did share a run time library. The rule was that the library used should be equal to or later version than the compiler. I remember the time when library support for implied DO in I/O lists was added, which meant that one must use the new library. (Before that, they were generated as loops in the compiled code.) The calling convention was fairly simple, though. > The various compilers for the same language will usually not share > their run time libraries. The little luck you have observed is a > result of you test cases being Fortrans that have "borrowed" their > run time libraries from a related C compiler. Some even claim that > they are not true compilers as they share the GCC back ends, but > that is an uninformed overstatement. (NAG can use other backends > on some platforms as well.)
I/O libraries can be a problem. In some cases it can work with separate I/O streams from two different library routines. If you don't do I/O, there is a much better chance that it will work. -- glen
On 2007-05-16 13:52:24 -0300, glen herrmannsfeldt <g@ugcs.caltech.edu> said: >> At one time in the past you could not even mix the object code >> from the IBM Fortran IV G and IBM Fortran IV H even though they >> shared a programmers manual. They had been writen by rather >> separate development groups with different objective. G was good >> at debugging and H was all about optimization. > I never knew about any incompatibilities. They did share > a run time library. The rule was that the library used > should be equal to or later version than the compiler. > I remember the time when library support for implied DO > in I/O lists was added, which meant that one must use the > new library. (Before that, they were generated as loops > in the compiled code.) The calling convention was fairly > simple, though.
An arcane problem on passed procedures was present that most folks did no see. But if you used a call back style, like many differential equation solvers did, then you could not mix libraries from the two compilers initially. It was fixed and then you could not mix pre-X code with post-X code as the change was to make one follow the convention the other had been using. My impression is that H was changed to follow the G convention. (Some folks claimed it was because the IBM staffers did not know how to modify the purchased G. At least it was a good story by those who did not always admire IBM!)
In article <1179323982.400235.202@n59g2000hsh.googlegroups.com>, Arjen Markus <arjen.mar@wldelft.nl> writes: > I know that the gfortran compiler and apparently its brother/cousin > g95 dropped binary compatibility with g77 because it was impossible to > maintain that compatibility.
It a little more complicated than the above with gfortran. There is the -ff2c option, which uses the g77 (aka f2c) call convention. So a library, compiled with g77, can be linked to code compiled with gfortran. The caveat, and it is big caveat, is IO. The g77 compiled library may or may not work with gfortran depending on the architecture and the type of IO. -- Steve http://troutmask.apl.washington.edu/~kargl/
Gordon Sande wrote:
(snip on OS/360 Fortran compatibility) > An arcane problem on passed procedures was present that most > folks did no see. But if you used a call back style, like many > differential equation solvers did, then you could not mix > libraries from the two compilers initially. It was fixed and > then you could not mix pre-X code with post-X code as the > change was to make one follow the convention the other had > been using. My impression is that H was changed to follow the > G convention. (Some folks claimed it was because the IBM > staffers did not know how to modify the purchased G. At least > it was a good story by those who did not always admire IBM!)
It may have been fixed before I started, which may have been around release 20. I can guess that one passed the address of the called routine, and the other passed the address of the address. -- glen
|
 |
 |
 |
 |
|