Как псевдоним имени функции в Фортран - PullRequest
27 голосов
/ 23 декабря 2011

Не уверен, что название правильно поставлено.Предложения приветствуются.

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

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

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

Есть идеи, как это можно реализовать?

Спасибо.

Ответы [ 2 ]

38 голосов
/ 23 декабря 2011

Да, в 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
3 голосов
/ 23 декабря 2011

Большинство реализаций Фортрана не имеют стандартного способа манипулировать указателями функций или указателями процедур.Тем не менее, 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.

...