Search code examples
debuggingfortrangfortrandimensionfortran77

Reduction of output array dimension in Fortran77 procedure


I am working on a large Fortran code, where parts are written in FORTRAN77. There is a piece of code, which causes debugger to raise errors like:

Fortran runtime error: 
Index '2' of dimension 1 of array 'trigs' above upper bound of 1

but when compiled without debugging options runs and does not crash the program. Debugging options used:

-g -ggdb -w -fstack-check -fbounds-check\
     -fdec  -fmem-report -fstack-usage

The logic of the problematic piece of code is following: in file variables.cmn I declare

implicit none

integer factors,n
real*8 triggers
parameter (n=32)

common /fft/ factors(19), triggers(6*n)

Variables factors and triggers are initialized in procedure initialize:

include 'variables.cmn'
...
CALL FFTFAX(n,factors,triggers)
...

FFTFAX is declared in another procedure as:

SUBROUTINE FFTFAX(N,IFAX,TRIGS)
implicit real*8(a-h,o-z)
DIMENSION IFAX(13),TRIGS(1)

    CALL FAX (IFAX, N, 3)
    CALL FFTRIG (TRIGS, N, 3)

RETURN
END

and lets look at procedure FFTRIG:

  SUBROUTINE FFTRIG(TRIGS,N,MODE)
  implicit real*8(a-h,o-z)
  DIMENSION TRIGS(1)

        PI=2.0d0*ASIN(1.0d0)
        NN=N/2
        DEL=(PI+PI)/dFLOAT(NN)
        L=NN+NN

        DO 10 I=1,L,2
        ANGLE=0.5*FLOAT(I-1)*DEL
        TRIGS(I)=COS(ANGLE)
        TRIGS(I+1)=SIN(ANGLE)
10 CONTINUE
        DEL=0.5*DEL
        NH=(NN+1)/2
        L=NH+NH
        LA=NN+NN

        DO 20 I=1,L,2
        ANGLE=0.5*FLOAT(I-1)*DEL
        TRIGS(LA+I)=COS(ANGLE)
        TRIGS(LA+I+1)=SIN(ANGLE)
20 CONTINUE

In both FFTFAX and FFTRIG procedures there are different bounds for dimensions of arguments than the actual input array size (for TRIGS it is 1 and 19, respectively). I printed out TRIGS after calling FFTFAX in no-debugger compilation setup:

 trigs:                    1.0000000000000000        0.0000000000000000\
  0.99144486137381038       0.13052619222005157       0.96592582628906831\
  0.25881904510252074       0.92387953251128674       0.38268343236508978\
  ...

My questions are:

  1. Is notation : DIMENSION TRIGS(1) something more than setting bound of an array?
  2. Why is the program even working in no-debugger mode?
  3. Is setting: DIMENSION TRIGS(*) a good fix if I want variable trigs be a result of the procedure?

Solution

  • In f77 statements like the DIMENSION TRIGS(1) or similar or ..(*) with any number, if pertaining an argument of the procedure just tells the compiler the rank of the array, the length in memory must be assigned to the array which is given in the call of the subroutine, normally f77 does not check this! My recommendation either use (*) or better reformat (if necessary) the f77 sources to f90 (the bits shown would compile without change...). and use dimension computed using n in the declaration within the subroutines/procedures. Fortan passes arguments by address (i.e. trigs(i) in the subroutine just will refer on the memory location, which corresponds to the address of trigs(1) + i*size(real*8).

    A more consisted way to write the subroutine code could be:

    SUBROUTINE FFTRIG(TRIGS,N,MODE)
    !   implicit real*8(a-h,o-z)
    integer, intent(in) :: n      
    real(kind=8)        :: trigs(6*n)
    integer             :: mode
    !  DIMENSION TRIGS(1)
    .....
        PI=2.0d0*ASIN(1.0d0)
    .....
    

    or with less ability for the compiler to check

    SUBROUTINE FFTRIG(TRIGS,N,MODE)
    !   implicit real*8(a-h,o-z)
    integer, intent(in) :: n      
    real(kind=8)        :: trigs(:)
    integer             :: mode
    !  DIMENSION TRIGS(1)
    .....
        PI=2.0d0*ASIN(1.0d0)
    .....