Когда я компилирую ваш код, я могу выполнить вызов к .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 для получения дополнительной информации.
Надеюсь, это поможет!