カプセル化された型バインド関数を渡す方法は? Modern Fortran Explained の本 (Metcalf、Reid、Cohen) の例で遊んだところ、次のようになりました。
module mod_polynoms_abstract
use mod_geometrics
implicit none
type, abstract :: bound_user_polynom
! No data
contains
procedure(user_polynom_interface), deferred :: eval
end type bound_user_polynom
abstract interface
real function user_polynom_interface(poly, pt)
import :: bound_user_polynom, point
class(bound_user_polynom) :: poly
type(point), intent(in) :: pt
end function user_polynom_interface
end interface
contains
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Integral driver/chooser function
real function integral(userfun, options,status)
class(bound_user_polynom) :: userfun
integer, intent(in) :: options
real, intent(out) :: status
select case( options )
case (1)
integral = first_integral(userfun)
case (2)
integral = second_integral(userfun)
case default
integral = def_integral(userfun)
end select
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!1. integration
real function first_integral(userfun)
class(bound_user_polynom),intent(in) :: userfun
first_integral= 1.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!2. integration
real function second_integral(userfun)
class(bound_user_polynom),intent(in) :: userfun
second_integral= 2.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!default integration
real function def_integral(userfun)
class(bound_user_polynom) :: userfun
def_integral= 0.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
end module
これはコンパイルされますが、プログラムを実行すると異なる結果が得られます。関数を呼び出すと、おそらく次のようになります。
integral_result = integral(poly, 2 , status)
second_integral(userfun) 関数で計算された正しい結果が得られることがあります。しかし、時には結果が間違っています。関数はuserfun%eval(point(x=2.,y=2.,z=0.))
正しく計算できませんが、その理由はわかりません。これはこれを行う正しい方法ですか?
編集:
私が使う :
COLLECT_GCC=gfortran4.8
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper
Ziel: x86_64-unknown-linux-gnu
Konfiguriert mit: ./configure --disable- multilib
スレッド モデル: posix
gcc-Version 4.8.0 (GCC)
userfun%eval(point(x=2.,y=2.,z=0.))の正しい結果は0.962435484です。しかし、プログラムを数回実行すると、次のようになりました。
最初の実行: 1.92487097
2 回目の実行: 54877984.0
...: 1.92487097
...: 2.55142141E+27
...: 4.19146938E+33
...: 1.95548379
など ..
編集2:
型多項式は次のように定義されます。
type, extends(bound_user_polynom) :: polynom
real(kind=kind(1.0D0)), allocatable, dimension(:) :: coeff
type(monomial),allocatable, dimension(:) :: monom
contains
procedure :: eval => poly_eval
procedure, private :: p_add
generic :: operator(+) => p_add
procedure, private :: p_subs
generic :: operator(-) => p_subs
end type
!constructor
interface polynom
module procedure construct_poly
end interface
私のメインプログラムでは、次のように呼び出します。
integral_result = integral(p(2), 2 , status)