Как псевдоним имени функции в Fortran
Не уверен, что заголовок хорошо помещен. Предложения приветствуются.
Вот что я хочу делать. Проверьте состояние и затем определите, какую функцию использовать в цикле. Например:
if (a < 0) then
loop_func = func1
else
loop_func = func2
endif
Затем я могу использовать loop_func
в качестве указателя при написании моего цикла. Обе функции принимают одинаковые входные данные и представляют собой различные подходы к решению проблемы, основанные на значении a
. Это позволит мне иметь только один блок кода вместо двух почти одинаковых блоков. Это также относится к подпрограммам.
Любые идеи, как это можно реализовать?
Спасибо.
Ответы
Ответ 1
Да, у Fortran есть указатели на процедуры, поэтому вы можете по существу псевдоним имени функции. Вот пример кода, который присваивает функции указателю "f_ptr" одну функцию или другую. После этого программа может использовать "f_ptr", и выбранная функция будет вызываться.
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
end module ExampleFuncs
program test_func_ptrs
use ExampleFuncs
implicit none
abstract interface
function func (z)
real :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr => null ()
real :: input
write (*, '( / "Input test value: ")', advance="no" )
read (*, *) input
if ( input < 0 ) then
f_ptr => f1
else
f_ptr => f2
end if
write (*, '(/ "evaluate function: ", ES14.4 )' ) f_ptr (input)
stop
end program test_func_ptrs
Ответ 2
Большинство реализаций Fortran не имеют стандартного способа манипулирования указателями функций или указателями процедур. Тем не менее, Fortran 2003 и более поздние версии имеют что-то. (См. Стр. 6 из this.)
Для данной ситуации это будет хорошо работать на своем месте:
function func1 (p1, p2, etc)
... as you have it already
end
function func2 (p1, p2, etc)
... as you have it already
end
function funcselect (a, p1, p2, etc)
if (a < 0) then
x = func1 (p1, p2, etc)
else
x = func2 (p1, p2, etc)
endif
end
Затем просто вызовите funcselect
с дополнительным параметром вместо того, что вы сделали бы с помощью loop_func
.