web-dev-qa-db-ja.com

Fortranで関数名をエイリアスする方法

タイトルがうまく入れられているかどうかわからない。提案を歓迎します。

これが私がやりたいことです。条件を確認してから、ループで使用する関数を決定します。例えば:

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

その後、ループを作成するときにloop_funcをポインターとして使用できます。どちらの関数もまったく同じ入力を受け取り、aの値に基づいて問題に取り組むための異なるアプローチです。これにより、ほぼ同一の2つのブロックではなく、1つのコードブロックのみを使用できるようになります。これはサブルーチンにも当てはまります。

これをどのように実装するかについてのアイデアはありますか?

ありがとうございました。

27
Samuel Tan

はい、Fortranにはプロシージャポインタがあるため、実際には関数名のエイリアスを作成できます。これは、関数ポインタ「f_ptr」に1つの関数または他の関数を割り当てるコード例です。その後、プログラムは「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
38
M. S. B.

ほとんどのFortran実装には、関数ポインターまたはプロシージャーポインターを操作するための標準的な方法がありません。ただし、Fortran2003以降には何かがあります。 ( this の6ページを参照してください。)

与えられた状況では、これはその場所でかなりうまく機能します:

 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

次に、loop_funcで行ったのではなく、追加のパラメーターを使用してfuncselectを呼び出します。

3
wallyk