Массивы указателей на функции в Фортране
Я могу создавать указатели на функции в Фортран 90, с кодом, как
real, external :: f
а затем использовать f
в качестве аргумента для другой функции / подпрограммы. Но что, если я хочу массив указателей на функции? В КИ просто делаю
double (*f[])(int);
создать массив функций, возвращающих double и принимающих целочисленный аргумент. Я попробовал самое очевидное,
real, external, dimension(3) :: f
но gfortran не позволяет мне смешивать ВНЕШНЕЕ и РАЗМЕРНОЕ. Есть ли способ сделать то, что я хочу? (Контекст для этого - программа для решения системы дифференциальных уравнений, поэтому я мог бы вводить уравнения, не имея миллиона параметров в моих подпрограммах.)
1 ответ
Объявление "real, external:: f" на самом деле не превращает "f" в полный указатель, поскольку вы не можете изменить процедуру, на которую оно указывает, - это позволяет вам передать эту единственную функцию в другую подпрограмму. вам также нужен атрибут указателя. Есть примеры на странице 267 "Фортрана 95/2003 объяснено" Metcalf, Reid & Cohen - поиск в Google по "указателю процедуры fortran" откроет эту страницу. Простой пример, близкий к вашему, это "real, external, pointer:: f_ptr". В качестве альтернативы: "процедура (f), указатель:: f_ptr". Это функция Fortran 2003: http://gcc.gnu.org/wiki/Fortran2003 и http://gcc.gnu.org/wiki/ProcedurePointers перечисляют частичную поддержку в gfortran, лучше всего с 4.5. Я не уверен, разрешено ли "измерение" напрямую, но вы можете назначить процедуру указателю, что обеспечивает большую гибкость. Вы также можете поместить указатель в производный тип, который может быть преобразован в массив.
Редактировать: вот пример кода, который работает с gfortran 4.5: Редактировать 2: строка закомментирована согласно комментариям ниже.
module ExampleFuncs
implicit none
contains
function f1 (x)
real :: f1
real, intent (in) :: x
f1 = 2.0 * x
return
end function f1
function f2 (x)
real :: f2
real, intent (in) :: x
f2 = 3.0 * x**2
return
end function f2
function fancy (func, x)
real :: fancy
real, intent (in) :: x
interface AFunc
function func (y)
real :: func
real, intent (in) ::y
end function func
end interface AFunc
fancy = func (x) + 3.3 * x
end function fancy
end module ExampleFuncs
program test_proc_ptr
use ExampleFuncs
implicit none
! REMOVE: pointer :: func
interface
function func (z)
real :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr => null ()
type Contains_f_ptr
procedure (func), pointer, nopass :: my_f_ptr
end type Contains_f_ptr
type (Contains_f_ptr), dimension (2) :: NewType
f_ptr => f1
write (*, *) f_ptr (2.0)
write (*, *) fancy (f_ptr, 2.0)
f_ptr => f2
write (*, *) f_ptr (2.0)
write (*, *) fancy (f_ptr, 2.0)
NewType(1) % my_f_ptr => f1
NewType(2) % my_f_ptr => f2
write (*, *) NewType(1) % my_f_ptr (3.0), NewType(2) % my_f_ptr (3.0)
stop
end program test_proc_ptr