R & Fortran Call - PullRequest
       44

R & Fortran Call

11 голосов
/ 19 января 2011

У меня нет опыта работы с Fortran, но я пытаюсь запустить очень простой цикл на этом языке, вызывая его из R с помощью функции .Fortran ().Всякий раз, когда я запускаю последнюю строку кода R, которая вставлена ​​ниже, графический интерфейс R вылетает, и я не получаю результата.Я заинтересован в возвращении вектора реальных значений x из Фортрана в R для дальнейшего анализа.g - это числовое значение от 0 до 1, а n - целое число, и оба они предоставляются пользователем в R.

Любая помощь будет принята с благодарностью!Best,

Vincent

Код Fortran, сохраненный в bar.f:

    subroutine bar(n, g, x)

      integer n
      double precision g
      double precision x(n)
      integer i
      x(1)=1
      do 100 i = 2, n
          x(i) = x(i-1) * g + 1
  100 continue

      end

Компиляция DLL в Cygwin с помощью gfortran:

gfortran -shared -obar.dll bar.f

Rкод:

dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))

1 Ответ

25 голосов
/ 19 января 2011

Когда я компилирую ваш код, я могу выполнить вызов к .Fortran один раз.Когда я запускаю его во второй раз, он падает.Однако я заметил, что если я сделаю вектор, переданный для x той же длины, что и целое число, переданное для n, то это должно быть, то есть:

.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )

Я могу запустить функцию столько разкак я хочу.Таким образом, проблема может заключаться в том, что вы говорите подпрограмме Fortran, с которой он имеет вектор длины 15, для работы, но посылаете только вектор длины 5. Это может привести к тому, что подпрограмма Fortran получит доступ к памяти, для которой не предполагается, чтообъяснил бы сбой.

Так как, похоже, вы все равно генерируете все значения x в подпрограмме, вы можете пропустить генерирование случайных чисел и просто отправить пустой вектор, используя функцию R's double(n), гдеn - длина пустого вектора, который вы хотите сгенерировать:

.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))

integer и character - это полезные функции, которые возвращают такие векторы, как double.

Также некоторыеДружеские предложения относительно стиля Fortran, поскольку вы упоминаете, что только начинаете работать с языком:

  • Возможно, было бы разумно назвать ваши файлы с расширением .f90 --- файлы, оканчивающиеся на *Предполагается, что большинство компиляторов 1025 * придерживаются старого формата «фиксированной формы», который является PITA, так как он был разработан для использования на перфокартах.

  • Операторы Do 100 ... 100 continue представляют собой стиль конечных циклов в Fortran 77. Современный эквивалент - Do .. end do.

  • С помощью функций и подпрограмм Фортрана целесообразно объявить «намерение» переменных, входящих и выходящих из подпрограммы.Доступны объявления о намерениях:

    • intent(in): Обозначает переменные, которые входят в подпрограмму только в качестве входных данных.Оказавшись внутри подпрограммы, они должны рассматриваться как параметры, и компилятор выдаст ошибку, если будет предпринята попытка их изменить.

    • intent(out): обозначает переменные, значения которых должны быть сгенерированывнутри рутины как выходы.Компилятор выдаст предупреждение, если переменная намерения не назначена в подпрограмме.

    • intent(inout): Обозначает переменные, которые могут входить в подпрограмму, несущую определенный набор значений, и выходить изподпрограмма с различными значениями.

    Установка намерений для переменных поможет компилятору генерировать предупреждения и ошибки, которые могут спасти вас от поиска ошибок.

  • Fortranимеет поведение по умолчанию, при котором любая переменная, не объявленная в заголовке подпрограммы, будет целым числом, если ее имя начинается с in, а в действительности - иначе.Это может привести к тому, что имена переменных с ошибками «волшебным образом» станут переменными, и компилятор не бросит глаз и не скажет вам.Установка implicit none в верхней части ваших подпрограмм отключает это поведение и позволяет компилятору уведомлять вас об ошибках, которые могут быть очень трудно отследить в противном случае.

Версия вашей подпрограммы, котораяпринятие этих предложений во внимание будет выглядеть следующим образом:

subroutine bar(n, g, x)
  implicit none

  integer, intent(in):: n
  double precision, intent(in):: g
  double precision, intent(inout):: x(n)

  integer:: i

  x(1) = 1
  do i = 2, n
    x(i) = x(i - 1) * g + 1
  end do

end subroutine bar

Также полезно позволить R скомпилировать ваши библиотеки с помощью подкоманды SHLIB R CMD:

R CMD SHLIB -o bar.dll bar.f90

Это скомпилирует ваши программы с библиотеками R, которые содержат полезные функции - такие как подпрограммы BLAS, подпрограммы статистики и методы, которые могут выводить информацию на консоль R.См. Написание расширений R, раздел 6 для получения дополнительной информации.

Надеюсь, это поможет!

...