Принудительное явное объявление переменной с помощью gfortran - PullRequest
2 голосов
/ 24 августа 2010

Я связываю код Fortran (F90) из Matlab, используя Mex, и иногда у меня происходит зависание Matlab.

В прошлом у меня происходило зависание из-за несоответствия между типами данных (скажем, целое число * 4 против целого числа * 8).

Код, который я связываю, имеет много неявно определенных переменных, поэтому мне интересно, существует ли скрытый конфликт типов данных, который возникает только изредка.

Чтобы исключить несоответствие типов данных как причину зависания, я бы хотел, чтобы компилятор требовал явного объявления всех переменных.

Вопросы:

  1. Как заставить gfortran требовать явного объявления всех переменных во время компиляции? В противном случае, есть ли способ хотя бы получить предупреждения?

  2. Является ли "реальный" тип данных интерпретируемым gfortran как специфический тип во всех архитектурах? Если да, то какой это (настоящий * 4, настоящий * 8, ...)?

  3. Можно ли заставить gfortran интерпретировать «настоящий» тип данных как определенный тип, скажем, «real * 4»?

  4. Есть идеи, что заставляет код fortran зависать при вызове из скомпилированной в mex подпрограммы в matlab (кроме несоответствия типов данных)?

Спасибо за любую помощь.

Пока я не пойму это, я буду проходить через множество строк кода, пытаясь перечислить все неявно определенные переменные. Само собой разумеется, я буду чрезвычайно благодарен любому, кто освобождает меня от такой скучной задачи ...

Best

G.

Ответы [ 4 ]

2 голосов
/ 25 августа 2010

IMPLICIT NONE и опция компилятора уже упомянута.

Давайте поговорим об арифметике с плавающей точкой. Проблема заключается в том, что (упомянутые здесь здесь ) MATLAB конструирует типы данных как двойной, так и двойной точности, или одинарной точности в соответствии с IEEE® Standard 754 , но Стандарт Fortran не требует его значения по умолчанию и двойной точности, чтобы соответствовать этому стандарту. Как вы можете видеть, стандартный документ даже использует другое имя (реальное по умолчанию, а не с одинарной точностью).

MODULE kinds

  IMPLICIT NONE

  INTEGER, PARAMETER :: fortran_default = kind(0.0)
  INTEGER, PARAMETER :: fortran_double = kind(0.0D0)
  INTEGER, PARAMETER :: ieee_single = selected_real_kind(7, 38)
  INTEGER, PARAMETER :: ieee_double = selected_real_kind(15, 307)

END MODULE kinds

Здесь, в первых двух строках моей спецификации видов, я использовал удобный способ получения видов для вещественных значений по умолчанию и вещественных чисел с двойной точностью. Следующие два вида соответствуют упомянутому стандарту IEEE.

PROGRAM main

  USE kinds

  IMPLICIT NONE

  REAL(kind=ieee_single) :: is
  REAL(kind=ieee_double) :: id
  REAL(kind=fortran_default) :: fs
  REAL(kind=fortran_double) :: fd

  PRINT *, kind(is), precision(is), range(is)
  PRINT *, kind(id), precision(id), range(id)
  PRINT *, kind(fs), precision(fs), range(fs)
  PRINT *, kind(fd), precision(fd), range(fd)

END PROGRAM main 

Вывод на моем компьютере (Mac OS X 10.6, gfortran 4.5.1):

   8          15         307
   8          15         307
   4           6          37
   8          15         307

Таким образом, реальный тип по умолчанию Фортрана не равен стандартному типу с плавающей точкой одинарной точности IEEE.

Так что это может быть источником ошибок. Точность где-то теряется, некоторая переменная становится равной 0,0, а не немного больше / меньше 0,0, а затем вы делитесь на это значение (которое в точности равно 0,0). Ну, это может заморозить программу.

2 голосов
/ 24 августа 2010

Как уже говорилось, в вашем исходном коде вы можете использовать неявное none . Преимущество заключается в том, что он переносим на все компиляторы.

С gfortran вы можете использовать опцию компилятора -fimplicit-none . Это преимущество заключается в том, что он будет отлавливать переменные, которые вы забыли явно указать, даже если вы забыли включить неявное значение none. Большинство других компиляторов имеют похожую опцию.

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

Что означает простое «настоящее», зависит от компилятора - если у вас есть особые требования, лучше использовать более конкретное объявление. Лучший способ - определить параметр с выбранным внутренним реальным видом и использовать его для аналогичного обсуждения: Фортран: целое число * 4 против целого числа (4) против целого числа (вида = 4)

1 голос
/ 24 августа 2010
  1. Вы можете потребовать явного объявления всех переменных, добавив implicit none.
  2. Я считаю, что "реальный" тип данных по умолчанию - real*4.
  3. Вы можете использовать флаг командной строки -fdefault-real-8, чтобы все переменные, объявленные как real, интерпретировались как real*8

Примечание (для написания большего количества кода не обязательно пытаться решить текущую ошибку): Если вы используете код Fortran 90, вы можете использовать real(kind=4) или real(kind=8) с gfortran вместо синтаксиса real*4 или real*8. Я отошел от установки реального или целочисленного размера с помощью флагов командной строки и вместо этого использую переменную integer, parameter :: REAL_SIZE для хранения соответствующего числа (обычно я выбираю 4 или 8, потому что все используемые мной компиляторы поддерживают их, но если если вы хотите быть очень переносимым, вы должны использовать процедуру selected_real_kind)

0 голосов
/ 24 августа 2010

Один из них работает с большинством компиляторов, поскольку Fortran 77:

implicit none

или

implicit undefined(a-z)

Real зависит от архитектуры;размер по умолчанию обычно можно изменить с помощью параметра командной строки.

У меня нет опыта работы с Matlab.

...