7

関数を引数として取るFortran90サブルーチンがあり、その関数の変更バージョンを別のサブルーチンに渡したいと思います。プログラムを次のようにしたいと思います。

subroutine foo(f, ...)
    real                 :: pt(2), dir(2)

    interface
    function f(x) result(y)
        real, intent(in) :: x(2)
        real             :: y
    end function f
    end interface

    pt = ...
    dir = ...
!! Somehow create g(x) = f(pt + x*dir)
    call bar(g)

end subroutine foo

subroutine bar(g)
    interface
    function g(x) result(y)
        real, intent(in) :: x
        real             :: y
    end function g
    end interface

!! Do stuff with g
end subroutine bar

'g'が関数ではなく通常の変数のみを使用する必要がある場合、私はなんとか同様のことを行うことができました。その場合、グローバル変数を使用してグローバル関数にし、「foo」でそれらのグローバル変数に割り当てました。ただし、「f」をグローバルにする方法、またはグローバル関数に割り当てる方法が見つかりません。

誰かがこれを行う方法について何かアイデアがありますか?解決策はあなたが望むようにハッキーにすることができます。

4

2 に答える 2

7

これはそれほど簡単ではありません。一部の言語では、ネストされた関数へのポインタを、いわゆるclosure. Fortran (または C および同様の言語) では、データが上位関数のスタックで破壊されるため、これは不可能です。class関数オブジェクト、つまり、関数に必要なfunction pointer(またはそれ以上の) およびデータを使用することをお勧めします。このようにして、関数の合成や同様の機能的なことを行うことさえできます。

概念の詳細http://en.wikipedia.org/wiki/Function_object

以下は、2 つの単一引数関数を合成するための関数オブジェクトのサンプルです。

module ComposeObj
  use Parameters, only: rp
  use AritmFunctions, only: fce
  implicit none

  private
  public Compose

  type Compose
    private
    procedure(fce),pointer,nopass :: f1 => null(),f2=>null()
  contains
    procedure,public :: call => helper
  end type 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(rp) function helper(this,x)
    class(Compose),intent(in) :: this
    real(rp),intent(in) :: x
    helper = this%f1(this%f2(x))
  end function helper

end module ComposeObj
于 2012-03-14T08:56:23.877 に答える
2

他の関数の組み合わせである関数を構築して、プロシージャ ポインターを使用して多くのことができます。コード例については、Fortran の関数ポインター配列を参照してください。

于 2012-03-14T03:56:17.603 に答える