2011-12-23 19 views
22

タイトルが適切かどうかわかりません。提案は大歓迎です。Fortranで関数名をエイリアスする方法

ここで私がしたいことがあります。条件を確認し、ループ内で使用する関数を決定します。たとえば、

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

私はループを書くときにポインタとしてloop_funcを使うことができます。両方の関数は全く同じ入力を受け取り、aの値に基づいて問題に取り組む際の異なるアプローチです。これにより、2つのほとんど同じブロックではなく、1つのコードブロックしか持てません。これはサブルーチンにも当てはまります。

これはどのように実装することができますか?

ありがとうございます。

答えて

31

はい、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 
+0

これはどのような方言ですか? – wallyk

+0

Hmm ... '=>'はポインタ用のある種の代入演算子であり、 'procedure(func)'は手続きのためのある種の宣言であり、 'type(mytype)'は派生型のようです。私は 'null()'が初期化に使用されていると仮定しており、0に相当します。あなたは私がこれで初心者だと言うことができます。そして、はい、Fortranは私が正しく学んでいる最初のプログラミング言語です。 –

+0

いくつか質問があります。 'インターフェース'とは何ですか?これはプロシージャを指定する方法(やはり派生型のように)であり、ポインタが指しているものが正しい "型"であることを保証する方法ですか?また、プログラムの最後の前に 'stop'があります。そのベストプラクティスですか、私も自分のコードに含める必要がありますか? –

2

ほとんどのFortran実装では、関数ポインタまたはプロシージャポインタを操作する標準的な方法はありません。しかし、Fortran 2003以降には何かがあります。 (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を呼び出します。

+0

ただし、プログラムが関数を呼び出すたびに条件をチェックする必要はありませんか?私はそれを避けようとしています。 –

+0

@ SamuelTan:はい、それは心配することはほとんどありません。最新のプロセッサでは、これはほんのわずかのCPUサイクルで、数ナノ秒です。 – wallyk

+2

私は、「Fortranには関数ポインタまたはプロシージャポインタを操作する標準的な方法がありません」という記述には同意しません。プロシージャ・ポインタは、Fortran 2003言語標準の一部です。 @ wallyk。 –

関連する問題