Подтвердить что ты не робот

Как псевдоним имени функции в Fortran

Не уверен, что заголовок хорошо помещен. Предложения приветствуются.

Вот что я хочу делать. Проверьте состояние и затем определите, какую функцию использовать в цикле. Например:

if (a < 0) then
    loop_func = func1
else
    loop_func = func2
endif

Затем я могу использовать loop_func в качестве указателя при написании моего цикла. Обе функции принимают одинаковые входные данные и представляют собой различные подходы к решению проблемы, основанные на значении a. Это позволит мне иметь только один блок кода вместо двух почти одинаковых блоков. Это также относится к подпрограммам.

Любые идеи, как это можно реализовать?

Спасибо.

4b9b3361

Ответ 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.