0

私は用語を知らない初心者なので、これに対する答えを Web で検索することはできません。

プログラミングで、このようなことをしたいと思ったことは一度ならずあります。

A と B はサブルーチン、c と d は関数です。A と B はそれぞれ、内部で関数を複数回呼び出します。

call A(c(x))
call A(d(x))
call B(c(x))
call B(d(x))

この構造は機能しません。少なくともこのコンテキストでは、Fortran は関数のエイリアシングをサポートしていないと言われています。(「エイリアシング」を含むほとんどの検索結果は、関数ではなくエイリアシング変数を参照しているため、答えが見つかりませんでした。)

では、A と B の複数のバージョンを作成せずにこれを行うには、どのような構造を使用すればよいでしょうか?

4

4 に答える 4

4

IanH がコメントで述べているように、 call A(c(x)) は evaluate c(x) のように見え、それをサブルーチン A に渡します。

X などの型の引数を取る関数 "C" をサブルーチン A に渡したい場合は、いくつかの方法があります。

すでに述べたように、プロシージャ ポインタは新しい方法です。Fortran 2003 標準をすべてサポートするコンパイラはほとんどありませんが、この部分は広くサポートされています。

これは、 Fortran の関数ポインター配列から適用された例です。

module ProcsMod

  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


subroutine fancy (func, x, answer)

   real, intent (in) :: x
   real, intent (out) :: answer

   interface AFunc
      function func (y)
         real :: func
         real, intent (in) ::y
      end function func
   end interface AFunc

   answer = func (x)

end subroutine fancy

end module  ProcsMod


program test_proc_ptr

  use ProcsMod

  implicit none

  interface
     function func (z)
        real :: func
        real, intent (in) :: z
     end function func
  end interface

  procedure (func), pointer :: f_ptr => null ()

  real :: answer

  f_ptr => f1
  call fancy (f_ptr, 2.0, answer)
  write (*, *) answer

  f_ptr => f2
  call fancy (f_ptr, 2.0, answer)
  write (*, *) answer


  stop

end program test_proc_ptr

「call fancy (f_ptr, 2.0, answer)」という呼び出しは同じように見えますが、関数ポインタ f_ptr が指す関数を変更することで、別の関数がサブルーチン fancy に渡されます。

これは、gfortran (バージョン 4.4 から 4.7) と ifort の両方でコンパイルされます。

于 2012-11-29T08:28:48.977 に答える
4

ご希望の内容がよくわかりませんが、以下のようなものでしょうか?

Program f

  Implicit None

  Interface
     Integer Function c( x )
       Implicit None
       Integer, Intent( In ) :: x
     End Function c
     Integer Function d( x )
       Implicit None
       Integer, Intent( In ) :: x
     End Function d
  End Interface

  Call a( 3, c )
  Call a( 4, d )

  Call b( 5, c )
  Call b( 6, d )

Contains

  Subroutine a( x, func )

    Integer, Intent( In ) :: x
    Interface
       Integer Function func( x )
         Implicit None
         Integer, Intent( In ) :: x
       End Function func
    End Interface

    Write( *, * ) 'In a. Func = ', func( x )

  End Subroutine a

  Subroutine b( x, func )

    Integer, Intent( In ) :: x
    Interface
       Integer Function func( x )
         Implicit None
         Integer, Intent( In ) :: x
       End Function func
    End Interface

    Write( *, * ) 'In b. Func = ', func( x )

  End Subroutine b

End Program f

Integer Function c( x )
  Implicit None
  Integer, Intent( In ) :: x
  c = 2 * x
End Function c

Integer Function d( x )
  Implicit None
  Integer, Intent( In ) :: x
  d = 10 * x
End Function d
Wot now? gfortran -std=f95 f.f90 
Wot now? ./a.out
 In a. Func =            6
 In a. Func =           40
 In b. Func =           10
 In b. Func =           60
Wot now? 

代替手段はプロシージャ ポインタですが、そのためには f2003 コンパイラが必要であり、それらはまだあまり一般的ではありません - 上記は f90 に戻っても問題なく、それよりも前でも External は必要なことを行いますが、エラー チェック機能は少なくなります。

于 2012-11-29T05:50:40.410 に答える
1

MSBの答えは、関数のエイリアシングの意味を説明していると思います。Fortran 用語は「手続きポインタ」です。これとイアンの答えの代わりに、プロシージャの仮引数 (必ずしもポインターではない) を使用することもできます。procedure宣言は F2003 以降でのみサポートされていますが、gfortran 4.7 と ifort 13 の両方がこれをサポートしていることに注意してください。(抽象)インターフェイスブロックの有無にかかわらず実行できます。

module dummy_procedure
  implicit none

  abstract interface
    real function myfunc(x)
      real, intent(in) :: x
    end function
  end interface

contains      
  subroutine a(func)
    ! Using the interface block:
    procedure(myfunc) :: func         
    print*, 'a:', func(.5)
  end subroutine

  subroutine b(func)
    ! Using the explicit interface of a known procedure:
    procedure(f1) :: func  
    print*, 'b:', func(.5)
  end subroutine

  real function f1(x)
    real, intent(in) :: x
    f1 = 2.0 * x
  end function

  real function f2(x)
    real, intent(in) :: x
    f2 = 3.0 * x**2
  end function
end module

andをf1andf2に直接渡すことができるようになりました。出力は期待どおりです。ab

program main
  use dummy_procedure
  call a(f1)  ! a: 1.0
  call a(f2)  ! a: 0.75
  call b(f1)  ! b: 1.0
  call b(f2)  ! b: 0.75
end program
于 2012-11-29T16:46:31.640 に答える
0

あなたが何をしようとしているのか理解できたら:

1) モジュールで関数を定義します。

2) モジュールを使用します。

3) 関数と入力データを別々の引数としてサブルーチンに提供します。

これが私のために働いたコードです:

module iterfuncs
contains

! two example functions:
function approach_golden_ratio(a) result(agr)
  agr=1./a+1.
end function approach_golden_ratio

function approach_other_ratio(a) result(aor)
  aor=1./(a-1)
end function approach_other_ratio

end module



program use_some_functions

use iterfuncs

real :: final_res

final_res=2.3
! call subroutine with 1st function
call iterate(final_res,approach_golden_ratio)
print *,final_res

final_res=2.3
! call subroutine with 2nd function
call iterate(final_res,approach_other_ratio)
print *,final_res

end program



subroutine iterate(res,func)

use iterfuncs

do n=1,100
  res=func(res)
enddo

return

end subroutine
于 2012-12-01T00:17:02.060 に答える