0
votes

I have a code in Fortran IV that I need to run. I was told to try to compile it in Fortran 77 and fix the error. So I named the file with a .f extension and tried to compile it with gfortran. I got the next error referring to the Fortran IV function copied below:

abel.f:432.24:

      REAL FUNCTION DGDT*8(IX,NV,XNG,FNG,GNG,X)
                        1
Error: Expected formal argument list in function definition at (1)

Since I'm not too familiar with Fortran I'd appreciate if someone can tell me how to fix this problem .

      REAL FUNCTION DGDT*8(IX,NV,XNG,FNG,GNG,X)                         AAOK0429
C                                                                       AAOK0430
C     THIS SUBROUTINE COMPUTES THE VALUE OF THE DERIVATIVE OF THE       AAOK0431
C     G-FUNCTION FOR A SLIT TRANSMISSION FUNCTION GIVEN BY A            AAOK0432
C     PIECE-WISE CUBIC SPLINE , WHOSE PARAMETERS ARE                    AAOK0433
C     CONTAINED IN XNG,FNG AND GNG.                                     AAOK0434
C                                                                       AAOK0435
      IMPLICIT REAL*8(A-H,O-Z)                                          AAOK0436
C                                                                       AAOK0437
C     ALLOWABLE ROUNDING ERROR ON POINTS AT EXTREAMS OF KNOT RANGE      AAOK0438
C     IS 2**IEPS*MAX(!XNG(1)!,!XNG(NV)!).                               AAOK0439
      INTEGER*4 IFLG/0/,IEPS/-50/                                       AAOK0440
      DIMENSION XNG(1),FNG(1),GNG(1)                                    AAOK0441
C                                                                       AAOK0442
C       TEST WETHER POINT IN RANGE.                                     AAOK0443
      IF(X.LT.XNG(1)) GO TO 990                                         AAOK0444
      IF(X.GT.XNG(NV)) GO TO 991                                        AAOK0445
C                                                                       AAOK0446
C       ESTIMATE KNOT INTERVAL BY ASSUMING EQUALLY SPACED KNOTS.        AAOK0447
   12 J=DABS(X-XNG(1))/(XNG(NV)-XNG(1))*(NV-1)+1                        AAOK0448
C       ENSURE CASE X=XNG(NV) GIVES J=NV-1                              AAOK0449
      J=MIN0(J,NV-1)                                                    AAOK0450
C       INDICATE THAT KNOT INTERVAL INSIDE RANGE HAS BEEN USED.         AAOK0451
      IFLG=1                                                            AAOK0452
C       SEARCH FOR KNOT INTERVAL CONTAINING X.                          AAOK0453
      IF(X.LT.XNG(J)) GO TO 2                                           AAOK0454
C       LOOP TILL INTERVAL FOUND.                                       AAOK0455
    1 J=J+1                                                             AAOK0456
   11 IF(X.GT.XNG(J+1)) GO TO 1                                         AAOK0457
      GO TO 7                                                           AAOK0458
    2 J=J-1                                                             AAOK0459
      IF(X.LT.XNG(J)) GO TO 2                                           AAOK0460
C                                                                       AAOK0461
C       CALCULATE SPLINE PARAMETERS FOR JTH INTERVAL.                   AAOK0462
    7 H=XNG(J+1)-XNG(J)                                                 AAOK0463
      Q1=H*GNG(J)                                                       AAOK0464
      Q2=H*GNG(J+1)                                                     AAOK0465
      SS=FNG(J+1)-FNG(J)                                                AAOK0466
      B=3D0*SS-2D0*Q1-Q2                                                AAOK0467
      A=Q1+Q2-2D0*SS                                                    AAOK0468
C                                                                       AAOK0469
C       CALCULATE SPLINE VALUE.                                         AAOK0470
    8 Z=(X-XNG(J))/H                                                    AAOK0471
C     TF=((A*Z+B)*Z+Q1)*Z+FNG(J)                                        AAOK0472
C     TG=((3.*A*Z+2.*B)*Z+Q1)/H                                         AAOK0473
C     DGDT=(TG-TF/X)/X                                                  AAOK0474
      DGDT=(3.*A*Z*Z+2.*B*Z+Q1)/H                                       AAOK0475
      RETURN                                                            AAOK0476
C       TEST IF X WITHIN ROUNDING ERROR OF XNG(1).                      AAOK0477
  990 IF(X.LE.XNG(1)-2D0**IEPS*DMAX1(DABS(XNG(1)),DABS(XNG(NV)))) GO    AAOK0478
     1 TO 99                                                            AAOK0479
      J=1                                                               AAOK0480
      GO TO 7                                                           AAOK0481
C       TEST IF X WITHIN ROUNDING ERROR OF XNG(NV).                     AAOK0482
  991 IF(X.GE.XNG(NV)+2D0**IEPS*DMAX1(DABS(XNG(1)),DABS(XNG(NV)))) GO   AAOK0483
     1 TO 99                                                            AAOK0484
      J=NV-1                                                            AAOK0485
      GO TO 7                                                           AAOK0486
   99 IFLG=0                                                            AAOK0487
C       FUNCTION VALUE SET TO ZERO FOR POINTS OUTSIDE THE RANGE.        AAOK0488
      DGDT=0D0                                                          AAOK0489
      RETURN                                                            AAOK0490
      END                                                               AAOK0491
3
Ye gods, there must be more modern code to do this! I don't) know the answer but an informed quick hack (so hacky it makes me shudder to suggest it) is to change the function decl to Real*8 Function dgdt( ... ) - Ian Bush
Not F77, not ever Fortran - Real*8 has never been any part of any standard, that's why I shuddered (people who know me will take the proverbial). - Ian Bush
Last I'm saying on this - who knows? Real*8 isn't defined by a Fortran standard so who knows how those characters will be understood by a given compiler in a given code. After all extensions are allowed by the standard, its just their interpretation isn't defined. - Ian Bush
I'd recommend to not stop at F77 and instead move to F90, with free form. There is, in my opinion, no valid argument for sticking to fixed format nowadays! Note, that gfortran is NOT a F77 compiler, but depending on the version more a F2003 compiler or even almost a F2008 compiler. - haraldkl
There are tools which allow you to do this automatically, for example: pypi.python.org/pypi/fixed2free2 - haraldkl

3 Answers

2
votes

This doesn't look so bad. Modern compilers still accept the real*8 syntax although it isn't standard. So you should (as mentioned) replace the line

  REAL FUNCTION DGDT*8(IX,NV,XNG,FNG,GNG,X)                         AAOK0429

with

  REAL*8 FUNCTION DGDT(IX,NV,XNG,FNG,GNG,X)                         AAOK0429

which compiled successfully for me using gfortran 4.6.2 using gfortran -c DGDT.f.

Good luck, and be on the lookout for other problems. Just because the code compiles does not mean it is running the same way it was designed!

0
votes

Not really an answer, see the one from Ross. But I just can't stand the requirement for fixed form. Here is how this code probably would look like in F90 with free form:

function DGDT(IX, NV, XNG, FNG, GNG, X)
  !  THIS FUNCTION COMPUTES THE VALUE OF THE DERIVATIVE OF THE
  !  G-FUNCTION FOR A SLIT TRANSMISSION FUNCTION GIVEN BY A
  !  PIECE-WISE CUBIC SPLINE, WHOSE PARAMETERS ARE
  !  CONTAINED IN XNG,FNG AND GNG.

  implicit none

  integer, parameter :: rk = selected_real_kind(15)

  integer :: ix, nv
  real(kind=rk) :: dgdt
  real(kind=rk) :: xng(nv)
  real(kind=rk) :: fng(nv)
  real(kind=rk) :: gng(nv)
  real(kind=rk) :: x

  ! ALLOWABLE ROUNDING ERROR ON POINTS AT EXTREAMS OF KNOT RANGE
  ! IS 2**IEPS*MAX(!XNG(1)!,!XNG(NV)!).
  integer, parameter :: ieps = -50
  integer, save :: iflg = 0
  integer :: j

  real(kind=rk) :: tolerance
  real(kind=rk) :: H
  real(kind=rk) :: A, B
  real(kind=rk) :: Q1, Q2
  real(kind=rk) :: SS
  real(kind=rk) :: Z

  tolerance = 2.0_rk**IEPS * MAXVAL(ABS(XNG([1,NV])))

  ! TEST WETHER POINT IN RANGE.
  if ((X < XNG(1) - tolerance) .or. (X > XNG(NV) + tolerance)) then
    ! FUNCTION VALUE SET TO ZERO FOR POINTS OUTSIDE THE RANGE.
    iflg = 0
    DGDT = 0.0_rk
    return
  end if

  ! ESTIMATE KNOT INTERVAL BY ASSUMING EQUALLY SPACED KNOTS.
  J = abs(x-xng(1)) / (xng(nv)-xng(1)) * (nv-1) + 1

  ! ENSURE CASE X=XNG(NV) GIVES J=NV-1
  J = MIN(J,NV-1)

  ! INDICATE THAT KNOT INTERVAL INSIDE RANGE HAS BEEN USED.
  IFLG = 1

  ! SEARCH FOR KNOT INTERVAL CONTAINING X.
  do
    if ( (x >= xng(j)) .or. (j==1) ) EXIT
    j = j-1
    ! LOOP TILL INTERVAL FOUND.
  end do
  do
    if ( (x <= xng(j+1)) .or. (j==nv-1) ) EXIT
    j = j+1
    ! LOOP TILL INTERVAL FOUND.
  end do

  ! CALCULATE SPLINE PARAMETERS FOR JTH INTERVAL.
  H = XNG(J+1) - XNG(J)
  Q1 = H*GNG(J)
  Q2 = H*GNG(J+1)
  SS = FNG(J+1) - FNG(J)
  B = 3.0_rk*SS - 2.0_rk*Q1 - Q2
  A = Q1 + Q2 - 2.0_rk*SS

  ! CALCULATE SPLINE VALUE.
  Z = (X-XNG(J))/H
  DGDT = ( (3.0_rk*A*Z + 2.0_rk*B)*Z + Q1 ) / H

end function DGDT

Note, I did not test this in any way, also there might be some wrong guesses in there, like that ieps should be a constant. Also, I am not so sure about iflg, and the ix argument does not appear to be used at all. So I might got something wrong. For the tolerance it is better to use a factor instead of a difference and a 2.**-50 will not change the value for a the maxval in a double precision number here. Also note, I am using some other F90 features besides the free form now.

0
votes

DISCLAIMER: Just mentioning a possible solution here, not recommending it...

As much as all other answers are valid and that supporting some Fortran IV code as is is a nightmare, you still might want / need to avoid touching it as much as possible. And since Fortran IV had some strange behaviours when it comes to loops for example (with loops always cycled at least once IINM), using a "proper" Fortran IV compiler might be a "good" idea.

Anyway, all this to say that the Intel compiler for example, supports Fortran IV natively with the -f66 compiler switch, and I'm sure other compilers do as well. This may be worth checking.