2016-07-26 8 views
0

Fortranでfunction compositionを作成したいとします。私がf(x)とg(x)を持っていれば、f(g(x))を見つけたいと考えています。 Pythonの構文では簡単ですBetter Function Composition in PythonFortranの関数の構成

module test10 
implicit none 
contains 
    function f5x (x) 
     real :: f5x 
     real, intent (in) :: x 
     f5x = 5.00*x 
    end function f5x 

    function f10x (x) 
     real :: f10x 
     real, intent (in) :: x 
     f10x = 10.00*x 
    end function f10x 


end module test10 


program call_test10 
    use test10 
    implicit none 
    real :: val1, val2, input 


    interface 
    real function fx_new (y) 
     real, intent (in) :: y 
    end function fx_new 
    end interface 


    input=1.0 
    write (*,*) 'Invoking f5x' 
    val1 = f5x(1.0) 
    write (*,*) val1 
    write (*,*) 'Invoking f10x' 
    val1 = f10x(1.0) 
    write (*,*) val1 
    write (*,*) 'Invoking f10x(f5x)' 
    procedure (fx_new), pointer :: ptr1 => f5x 
    procedure (fx_new), pointer :: ptr2 => f10x 
    val2 = ptr2(ptr1) 
    write (*,*) val2 

end program call_test10 

自身によって実行するステートメントval1 = f5x(1.0)val1 = f10x(1.0):ここ

は、サンプルのFortranコードです。しかし、機能構成に関しては、Fortranでどのように達成するかわかりません。私はf10x(f5x)を評価して、xに値を割り当てたいと思っています。何か案は?

モジュールファイルと関数の戻り値の型、引数の数、および引数の型が一致する場合、Fortranコンパイラはインクルードされたファイルで実行する関数を決定できますか?私が知りたいもう一つのことは、インタフェースを取り除くことができるかどうかです(プロシージャポインタなどを使用して)?外部関数を実行するためのインタフェースの考え方は私には分かりにくいので、可能であれば、インタフェースなしで外部関数を実行する方法を提案してください。私はキーワードexternalを知っていますが、それは以前のバージョンのためのものでした(新しい標準では動作し続けていますが)。

手続きポインタは、新しい基準(2003、2008、...)にあるように、私は2008年

+0

fortranでは閉鎖ができません。 – wey273824

+1

ポインタ型バインドプロシージャによるユーザ定義の派生データ型と 'iso_c_binding'中の' c_f_pointer'プロシージャを使ったC言語スタイルのキャストの両方に頼らずにこの作業を達成できるとは思いません。とにかく、関数の構成は、引数がFortranでどのように渡されるかに違反します。参照:https://software.intel.com/en-us/blogs/2009/03/31/doctor-fortran-in-ive-come-here-for-an-argument – jlokimlin

答えて

1

Fortranの標準を使用することになり、私はそれはあなたがそれがしたい方法も可能だとは思いません。

私が開始する前に:このようなことを可能にする言語でさえ、ptr2(ptr1)のようなものを入力した場合、結果は値ではなく関数になります。あなたはREAL変数にそれを格納することはできません。

あなたはこのように、独自の関数を書くことができ:

function my_func(x) 
    use test10, only: f5x, f10x 
    implicit none 
    real, intent(in) :: x 
    real :: my_func 
    my_func = f10x(f5x(x)) 
end function my_func 
0

これは多分それを見ての素朴な方法を少しですが、Fortranは、引数として渡す機能を許可するので、あなたが持っている可能性があり:

real function f(x, g) 
external g 
real x 
is_g_present = PRESENT(g) 

if is_g_present: 
    ! Do something with g and x 
else: 
    ! Do f(x) normally 
endif 
return 

これにより、fをf(x)またはf(x、g)として呼び出すことができます。それはあなたが求めているものではありませんが、Fortranにとってすばらしい、簡単な回避策です。

(私は今は全く愚かな何かを書いていないよテストするためのマシンを持っていないので、擬似コード、私はコメントとしてこれを書きますが、私は現時点では評判が欠如し、申し訳ありません)

+0

「外部」ステートメントは悪夢です維持する。 – jlokimlin

4

これはすでにここに示した例ですDynamic function creation from another function(あなたは検索しましたか?)私は質問が正確な複製ではないと思うので、私は閉じるのではなく再利用しています。他の人がこれを確認できます。

module ComposeObj 
    !here use modules defining your working kind as you wish 

    implicit none 

    private 
    public Compose 

    abstract interface 
    !declare fce as a function of the type you wish, probably a real function of a real variable  
    end interface 

    type Compose 
    private 
    procedure(fce),pointer,nopass :: f1 => null(),f2=>null() 
    contains 
    procedure,public :: call => helper 
    endtype Compose 

    interface Compose 
    procedure NewCompose 
    end interface 

contains 

    function NewCompose(f,g) 
    procedure(fce) :: f,g 
    type(Compose) :: NewCompose 

    NewCompose%f1 => f 
    NewCompose%f2 => g 
    end function NewCompose 

    pure real(work_kind) function helper(this,x) 
    class(Compose),intent(in) :: this 
    real(work_kind),intent(in) :: x 
    helper = this%f1(this%f2(x)) 
    end function helper 

end module ComposeObj 

基本的に、機能構成を行うことができるクラスを事前に準備する必要があります。その場でクロージャを作成するだけではいけません。

しかし、関数ポインタは、事前に行う必要のない機能に動的に割り当てることができます。

%call(x)メソッドを使用する必要がありますが、()はFortranの演算子ではないため(C++にあります)()をオーバーライドすることはできません。ローカル

type(Compose) :: f1_f2 
    f1_f2 = Compose(f1, f2) 

    val2 = f1_f2%call(x) 

、あなたは内部機能を使用することができます。私と他の人によって何度もここに示されてきました。すべてを繰り返す価値はありません。

val2 = composed_f1_f2(x) 

contains 

    function composed_f1_f2(x) 
    real :: composed 
    real, intent(in) :: x 
    composed = f1(f2(x)) 
    end function