Fortran: реализация подпрограммы, которая принимает другую подпрограмму в качестве аргумента в Fortran 90/95.
Я хотел бы написать подпрограмму Fortran, которая принимает имя другой подпрограммы в качестве аргумента - представьте, что первая подпрограмма является решателем PDE, а вторая обеспечивает правую часть PDE. Обратите внимание, что вторая подпрограмма может быть реализована другими, и поэтому мы можем ничего не знать о ней, кроме ее подписи.
Это возможно с использованием абстрактных интерфейсов и операторов процедуры. См., Например, https://github.com/jacobwilliams/PowellOpt/blob/master/src/newuoa.f90
Конечно, это также можно сделать с помощью внешних функций: http://malayamaarutham.blogspot.com/2006/02/passing-function-names-as-arguments-in.html
Однако абстрактные интерфейсы и операторы процедур доступны только после Fortran 2003, а внешние функции нежелательны. А вот и мой первый вопрос:
Можно ли передать имя подпрограммы в качестве аргумента в Fortran 90/95 без использования абстрактных интерфейсов и операторов процедур или внешних функций?
Вначале ответ показался мне отрицательным, потому что я видел это обсуждение: http://computer-programming-forum.com/49-fortran/dba58f497a8dc996.htm
К счастью, после дополнительных исследований я обнаружил, что это возможно через обычный интерфейс (не абстрактный), согласно таким источникам, как Fortran | Передача функций в качестве аргументов других функций, как передать имена подпрограмм в качестве аргументов в Fortran?, https://www.tek-tips.com/viewthread.cfm?qid=1572869.
Я реализовал следующий фрагмент кода в качестве минимального рабочего примера. Мой второй вопрос:
Соответствует ли следующий фрагмент кода Fortran 90/95?
Я пробовал скомпилировать код с помощью gfortran, ifort и g95. Первые два компилятора были довольны, но g95 выдвинул предупреждение, что
use fun_mod, only : fun
1
Warning (102): MODULE PROCEDURE 'fun' USEd at (1) is not referenced
когда я казнил
g95 -Wall -Wextra -std=f95 -pedantic main.f90
Полученный исполняемый файл работал без проблем, но почему это предупреждение? Это глюк g95? Если нет, то как избавиться от этого предупреждения? Любые другие комментарии / критика кода также будут высоко оценены.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module proc_mod
! PROC_MOD provides a subroutine PROC(X, Y, F) that invokes a subroutine
! F at (X, Y) and then increment Y by 1.
implicit none
private
public :: proc
contains
subroutine proc(x, y, f)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: y
interface
subroutine f(x, y)
real, intent(in) :: x(:)
real, intent(out) :: y
end subroutine f
end interface
call f(x, y)
y = y + 1.0
end subroutine proc
end module proc_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module fun_mod
! FUN_MOD provides a subroutine FUN(X, Y) that sets Y = SUM(X**2).
! In practice, this module is provided by OTHERS, and we do not
! know how it is implemented except for the signature of FUN.
implicit none
private
public :: fun
contains
subroutine fun(x, y)
implicit none
real, intent(in) :: x(:)
real, intent(out) :: y
y = sum(x**2)
end subroutine fun
end module fun_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program main
! MAIN tests PROC(X, Y, FUN) with PROC from PROC_MOD and FUN from FUN_MOD.
use proc_mod, only : proc
use fun_mod, only : fun
implicit none
real :: x(3), y
call random_number(x)
print *, x
call proc(x, y, fun)
print *, y
print *, sum(x**2) + 1.0
end program main
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Обратите внимание, что в этом коде нам нужно написать блок интерфейса для FUN в каждой подпрограмме, которая получает FUN в качестве аргумента. Было бы утомительно, если бы у меня было много таких подпрограмм. Это мотивирует мой третий вопрос:
Можно ли обернуть интерфейс FUN в модуль и обойтись без интерфейсного блока с помощью модуля?(Я пытался, но безуспешно.)
Большое спасибо!
Изменить: как указано @Ian Bush и @francescalus, возможно, мне следует согласиться с использованием абстрактных интерфейсов и операторов процедур, проверяя, реализуют ли компиляторы пользователей такую функцию F2003. Итак, вот 4-й вопрос:
Какая самая ранняя версия широко используемых компиляторов Фортрана (gfortran, ifort, nagfor, pgfortran...), реализующая абстрактный интерфейс и оператор процедуры?
Я знаю, что должен сам проверить документацию - обязательно. Я задаю этот вопрос здесь на всякий случай, если кто-то знает ответ. Позже я отредактирую вопрос, включив в него ответ на случай, если кто-то еще ищет то же самое. Спасибо.
Ответ на четвертый вопрос:
- gfortran: 4.3 (согласно https://gcc.gnu.org/wiki/GFortran/News), выпущен в 2008 г.
- nagfor: 5.1 (согласно http://geco.mines.edu/software/nagfor/nag_f2003.html), выпущенный в 2008 г.
- IBM XL Fortran для Linux или AIX: не позднее 12.1 (согласно http://publibfp.dhe.ibm.com/epubs/pdf/c2385550.pdf и https://www.ibm.com/support/pages/sites/default/files/support/swg/swgdocs.nsf/0/5f70ca824c75701b852574720069a576/%24FILE/compiler.pdf), выпущенный в 2008 г.
- ifort: 11.0 (согласно https://jp.xlsoft.com/documents/intel/compiler/11/Release_Notes_f_osx.pdf), выпущен в 2009 г.
- pgfortran: 10.8 (согласно https://www.pgroup.com/support/new_rel_2010.htm), выпущен в 2010 г.
- absoft Fortran: 14.0 (согласно https://www.absoft.com/wp-content/uploads/2015/08/ProFortran2014WindowsReleaseNotes.pdf и http://www.gmsl.it/wp-content/uploads/2014/09/Fortran_Reference.pdf), выпущенный в 2014 г.