Уменьшение размера выходного массива в процедуре Fortran77 - PullRequest
0 голосов
/ 11 мая 2018

Я работаю над большим кодом на Фортране, где части написаны на FORTRAN77. Есть фрагмент кода, который заставляет отладчик выдавать ошибки вроде:

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

но при компиляции без параметров отладки запускается и не вылетает программа. Используемые параметры отладки:

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

Логика проблемного фрагмента кода следующая: в файле variables.cmn я заявляю

implicit none

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

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

Переменные factors и triggers инициализируются в процедуре initialize:

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

FFTFAX объявлен в другой процедуре как:

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

и давайте посмотрим на процедуру 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

В процедурах FFTFAX и FFTRIG границы измерения аргументов отличаются от фактического размера входного массива (для TRIGS это 1 и 19 соответственно). Я напечатал TRIGS после вызова FFTFAX в настройке компиляции без отладчика:

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

Мои вопросы:

  1. Является ли обозначение: РАЗМЕРЫ ТРИГОВ (1) что-то большее, чем установка границ массива?
  2. Почему программа работает даже в режиме без отладки?
  3. Установлено: ТРИГИ ИЗМЕРЕНИЯ (*) хорошее решение, если я хочу, чтобы переменные триги были результатом процедуры?

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Чтобы ответить на ваш вопрос, я бы изменил TRIGS (1) на TRIGS (*), только для более четкой идентификации массива TRIGS как не имеющего размерности.TRIGS (1) является переносом из F77 до того, как идентифицировать это.

Использование TRIGS (:) неверно, так как для определения массива TRIGS таким образом требуется, чтобы любая подпрограмма, вызывающая FFTRIG, имела определение INTERFACE.Это изменение может привести к другим ошибкам.

Ваш вопрос состоит в том, чтобы смешать потребность отладчика в размере массива в сравнении с синтаксисом, исключая предоставляемый размер.Чтобы преодолеть это, вы можете передать объявленное измерение массива TRIGS в качестве дополнительного объявленного аргумента для проверки отладчиком.При использовании режима «отладчик» некоторые компиляторы предоставляют скрытые свойства, включая объявленный размер всех массивов.

0 голосов
/ 11 мая 2018

В операторах f77, таких как DIMENSION TRIGS (1) или аналогичных или .. (*) с любым числом, если принадлежащий аргумент процедуры просто сообщает компилятору ранг массива, длина в памяти должна быть назначенамассив, который дается в вызове подпрограммы, обычно f77 не проверяет это!Я рекомендую использовать (*) или лучше переформатировать (если необходимо) источники f77 в f90 (показанные биты будут компилироваться без изменений ...).и использовать измерение, вычисленное с использованием n в объявлении в подпрограммах / процедурах.Фортан передает аргументы по адресу (т.е. триггеры (i) в подпрограмме просто ссылаются на ячейку памяти, которая соответствует адресу триггеров (1) + i * size (real * 8).

A moreСоставной способ написания кода подпрограммы может быть:

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)
.....

или с меньшей возможностью для компилятора проверять

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)
.....
...